1 điểm bởi GN⁺ 2025-06-07 | 1 bình luận | Chia sẻ qua WhatsApp
  • Cơ sở dữ liệu OLTP dành cho kế toán kép TigerBeetle nhấn mạnh tính an toàn và tốc độ; Jepsen đã kiểm chứng các phiên bản 0.16.11~0.16.30 trên cụm Debian 3~6 máy kèm tiêm lỗi
  • Bài kiểm thử kết hợp thứ tự timestamp tường minh với mô hình máy trạng thái đơn luồng dựa trên tài liệu để kiểm tra đồng thời Strong Serializability và ngữ nghĩa tài khoản, chuyển khoản, truy vấn
  • Các lỗi an toàn chính là thiếu kết quả trong truy vấn nhiều bộ lọc và lỗi timestamp ở header của client Java; từ 0.16.26 trở lên, kết quả quan sát được nhất quán với tuyên bố Strong Serializability ngay cả dưới nhiều tổ hợp lỗi
  • Về tính sẵn sàng, các vấn đề được phát hiện gồm client retry vô hạn, tiến trình crash khi eviction session, độ trễ tăng vọt khi lỗi một node, server panic khi bit flip trên đĩa hoặc trong lúc nâng cấp, và thiếu đường dẫn khôi phục khi mất đĩa trên một node
  • TigerBeetle 0.16.43 đã phản ánh phần lớn các vấn đề được báo cáo, bao gồm giảm độ trễ khi lỗi một node và tigerbeetle recover; người vận hành cần kiểm tra release notes khi nâng cấp lên 0.16.43 và khi chuyển sang 0.16.26 trở lên

Thiết kế của TigerBeetle và phạm vi kiểm thử

  • TigerBeetle là cơ sở dữ liệu OLTP dành cho kế toán kép, chỉ lưu tài khoản (accounts) và chuyển khoản (transfers) thay vì các hàng, object, graph hay blob tùy ý
  • Dựa trên Viewstamped Replication (VR), TigerBeetle cam kết cung cấp tính nhất quán Strong Serializable, và được thiết kế phù hợp với các mô hình như giao dịch tài chính, tồn kho, bán vé, đo đếm tiện ích
  • Nhắm tới workload có mức tranh chấp cao và thông lượng lớn, mọi thao tác ghi đều đi qua một lõi đơn của node VR primary, tập trung vào scale-up hơn là scale-out
    • Để đạt hiệu năng, hệ thống dùng xử lý theo batch, song song hóa I/O, schema cố định, và cấu trúc dữ liệu kích thước cố định, căn chỉnh theo cache
  • Mô hình lỗi xử lý tường minh bộ nhớ, tiến trình, đồng hồ, lưu trữ và mạng
    • Tiến trình có thể dừng hoặc crash
    • Đồng hồ có thể nhảy tiến hoặc lùi
    • Đĩa không chỉ có thể hỏng hoàn toàn mà còn có thể gặp hỏng ghi một phần và nhiễm bẩn dữ liệu
    • Mạng có thể gây trễ, drop, trùng lặp, gửi sai đích và làm hỏng thông điệp
  • TigerBeetle sử dụng kiểm thử mô phỏng tất định; kiểm thử VOPR mô phỏng toàn bộ cụm cùng các giao diện đồng hồ, đĩa và mạng

Mô hình dữ liệu và ngữ nghĩa request

  • Mô hình dữ liệu gồm hai loại record: accountstransfers
    • Tài khoản có id 128-bit do người dùng đặt, ledger, flags, timestamp, code, user_data_32, user_data_64, user_data_128, v.v.
    • Chuyển khoản là record bất biến gồm debit_account_id, credit_account_id, amount, ledger, flags, các trường tùy chỉnh, v.v.
  • Chuyển khoản có thể được post ngay trong một bước, và cũng hỗ trợ chuyển khoản 2 bước chia thành pending và post/void
    • Pending transfer giữ chỗ dung lượng của tài khoản debit và credit
    • Sau đó có thể post hoặc void một số tiền không vượt quá pending amount
    • Trường timeout điều khiển việc tự động hết hạn
  • Tài khoản là bất biến ngoại trừ cờ closed và bốn trường số dư; chuyển khoản luôn bất biến
    • Muốn thay đổi hoặc đảo ngược một chuyển khoản thì phải tạo một chuyển khoản bù trừ mới
  • Mỗi request biểu diễn một loại thao tác logic duy nhất, thường chứa batch tối đa 8190 sự kiện
    • create_accounts, create_transfers là request ghi
    • lookup_accounts, lookup_transfers, query_accounts, query_transfers, get_account_transfers, get_account_balances là request đọc
  • Theo góc nhìn của cơ sở dữ liệu, mỗi request là một transaction, nhưng một số sự kiện trong request đã commit vẫn có thể thất bại về mặt logic và trả về mã lỗi
    • Nếu cần tính nguyên tử có điều kiện giữa các sự kiện, dùng chain để mọi sự kiện trong cùng một chain cùng thành công hoặc cùng thất bại

Cách kiểm thử của Jepsen

  • Bộ kiểm thử Jepsen dùng thư viện kiểm thử Jepsen để kết hợp kiểm thử dựa trên thuộc tính với tiêm lỗi
  • Đối tượng kiểm thử là TigerBeetle từ 0.16.11 đến 0.16.30, bao gồm cả một số bản build phát triển
    • Cụm gồm 3~6 node Debian
    • Chạy trên cả container LXC lẫn VM EC2
  • Client chính thức của TigerBeetle là smart client kết nối tới mọi node, nên có thể che giấu lỗi đồng thời
    • Jepsen cũng kiểm thử hành vi smart-client thông thường
    • Đồng thời cũng dùng cách giới hạn mỗi client vào một node duy nhất
  • Bộ kiểm chứng hoạt động theo hai giai đoạn
    • Đọc timestamp thực thi của request thành công, rồi suy luận timestamp của các thao tác ghi thất bại hoặc timeout từ hiệu ứng được quan sát sau đó
    • Chạy mô hình máy trạng thái TigerBeetle dựa trên tài liệu theo thứ tự timestamp suy luận được để kiểm chứng kết quả và mã lỗi
  • Mô hình máy trạng thái được viết bằng hơn 1.600 dòng Clojure, bao gồm map tài khoản/chuyển khoản, chỉ mục, transient error, thống kê nội bộ, dòng chảy thời gian, v.v.
    • Xử lý ID trùng, timestamp không đơn điệu, ràng buộc số dư, cờ không tương thích, speculative execution và rollback của chain, v.v.
    • Sử dụng thư viện cấu trúc dữ liệu bền vững hiệu năng cao Bifurcan

Tiêm lỗi và kiểm thử hỏng file

  • Jepsen tiêm SIGKILL, SIGSTOP cho tiến trình, nhiều dạng phân vùng mạng, thay đổi đồng hồ từ vài mili giây đến hàng trăm giây, và thay đổi đồng hồ qua lại nhanh
  • Trong quá trình kiểm thử cũng thực hiện nâng cấp node qua nhiều phiên bản
  • Một nemesis gây hỏng file mới đã tạo ra nhiều lỗi lưu trữ khác nhau
    • Mô phỏng hỏng hóc như nhiễu tia vũ trụ bằng cách flip bit ngẫu nhiên
    • Mô phỏng misdirected write bằng cách thay thế chunk file này bằng chunk khác
    • Mô phỏng lost write bằng cách lưu snapshot chunk file rồi khôi phục lại sau
  • Node TigerBeetle có một file dữ liệu duy nhất, file này được chia thành các zone ở offset dự đoán được
    • Thực hiện kiểm thử chỉ làm hỏng một số zone cụ thể như WAL header, các bản sao dư thừa của superblock zone
    • Cũng bao gồm kiểm thử làm hỏng nhiều zone hoặc toàn bộ file
  • Lỗi đĩa “helical” làm hỏng file trên tất cả node, nhưng mỗi node bị hỏng chunk khác nhau
    • Mục đích là tránh tình huống một record duy nhất bị hỏng đến mức không thể khôi phục trên mọi replica, vì bố cục file replica mới nhất của TigerBeetle thường giống nhau từng bit
    • Head của WAL có thể nằm ở vị trí khác nhau trên từng node, nên là ngoại lệ

Các vấn đề về an toàn được phát hiện

  • Trong 0.16.13, các phản hồi query_accounts, query_transfers, get_account_transfers thường gặp vấn đề bỏ sót một phần hoặc toàn bộ kết quả
    • Kết quả bị thiếu luôn nằm ở phần cuối phản hồi, và phản hồi là một prefix của kết quả đúng
    • Không xuất hiện ở truy vấn với một bộ lọc, mà xảy ra với các tổ hợp nhiều bộ lọc như ledgercode
    • Nguyên nhân là lỗi kiểm tra bounds trong zig-zag merge join giữa nhiều chỉ mục
    • Được theo dõi tại #2544 và đã sửa trong 0.16.17
  • API header của client Java được bổ sung trong 0.16.13 để hỗ trợ kiểm thử Jepsen trả về timestamp thực thi sai hoặc trùng lặp
    • Nguyên nhân là đối tượng phản hồi singleton mutable Batch.EMPTY của client Java
    • Khi phản hồi thành công được biểu diễn bằng batch rỗng, nhiều phản hồi ghi đè header của cùng một đối tượng
    • Đã sửa bằng #2495 và được đưa vào 0.16.14
    • Không ảnh hưởng đến tính nhất quán dữ liệu thực tế, chỉ ảnh hưởng đến timestamp yêu cầu của API header trong client Java
  • Các kết quả quan sát được từ 0.16.26 trở lên phù hợp với tuyên bố Strong Serializability của TigerBeetle
    • Thuộc tính này vẫn được duy trì ngay cả khi kết hợp pause process, crash, network partition, clock error, disk corruption và upgrade

Vấn đề ở client và xử lý yêu cầu

  • Tài liệu TigerBeetle mô tả rằng yêu cầu không bị timeout và client tiếp tục retry cho đến khi nhận được phản hồi
    • Các phương thức bất đồng bộ của Java trả về CompletableFuture và có thể dùng các API timeout như .get(timeout, timeUnit) hoặc .orTimeout(...)
    • Task của client .NET cũng cung cấp Wait() dựa trên timeout
  • Retry vô hạn có thể che giấu cả definite error lẫn indefinite error
    • Ví dụ, nếu kết nối TCP thất bại với ECONNREFUSED, đó là definite failure vì yêu cầu gốc không thể được thực thi
    • Nhưng nếu client không thông báo điều này cho bên gọi mà chỉ tiếp tục retry nội bộ, thì dưới góc nhìn của bên gọi nó trở thành indefinite failure như timeout hoặc bị dừng
  • Vấn đề này đang được thảo luận trong #206 và tại thời điểm báo cáo vẫn chưa được giải quyết
    • Jepsen khuyến nghị biểu diễn definite error và indefinite error như các lỗi hạng nhất và trả về cho bên gọi
    • Có thể duy trì retry tự động, nhưng nên cho phép cấu hình, đồng thời khuyến nghị đặt các tùy chọn cho thời gian tối đa khi khởi tạo kết nối và chờ phản hồi
  • Client Java 0.16.11 gặp vấn đề khiến toàn bộ JVM bị segfault khi interrupt thread gọi đồng bộ để xử lý timeout hoặc khi close client sau lời gọi bất đồng bộ
    • Nguyên nhân là một field chưa được đặt trong request data structure
    • Nếu client bị đóng giữa lúc tạo và gửi request, nó sẽ dereference địa chỉ mặc định 0xaaa... của Zig
    • Đã sửa bằng #2435 và được đưa vào 0.16.12
  • Client chính thức từng làm crash toàn bộ process khi server thông báo session eviction
    • TigerBeetle mặc định giới hạn concurrent session ở 64
    • Eviction cũng xảy ra khi dùng phiên bản client mới hơn server
    • Sau #2484, từ 0.16.13 trở đi, khi eviction xảy ra, client trả về error cho bên gọi thay vì làm crash process

Độ trễ tăng vọt khi một nút gặp lỗi

  • Trong trường hợp một nút gặp lỗi, client latency nhiều lần tăng thêm 3 đến 5 chữ số
    • Trong cụm 5 nút, khi kill một nút, minimum latency tăng từ dưới 1ms lên 10 giây
    • Trong thử nghiệm kill một nút ở cụm 3 nút, latency vốn là 1–50ms tăng lên khoảng 100 giây mỗi yêu cầu và kéo dài gần 1000 giây cho đến khi nút được khởi động lại
  • Nguyên nhân liên quan đến cách TigerBeetle lan truyền prepare
    • VR truyền thống để primary gửi prepare tới tất cả secondary và nhận ack trực tiếp
    • TigerBeetle sắp xếp các nút theo ring; khi primary gửi prepare tới secondary kế tiếp, mỗi secondary chuyển tiếp tới nút tiếp theo
    • Cách này giảm yêu cầu bandwidth của một nút, nhưng nếu một trong f replica kế tiếp trên ring bị lỗi, commit có thể bị chặn
  • Vấn đề này được theo dõi tại #2739
  • 0.16.30 giảm nhẹ vấn đề bằng cách gửi một nửa số thông điệp prepare theo hướng ngược lại trên ring
    • Một số prepare có thể đi vòng qua nút bị lỗi
    • Trong kiểm thử Jepsen, latency ở mức hàng trăm giây giảm xuống khoảng 1–30 giây
  • 0.16.43 bao gồm thêm các cải tiến hiệu năng
    • Các nút replicate theo cả hai hướng trên ring
    • Ring topology thay đổi động, và cụm điều chỉnh thứ tự nút theo điều kiện mạng và lỗi

Hỏng đĩa và server crash

  • Trong 0.16.20, có trường hợp hỏng một bit ở superblock, WAL hoặc grid zone gây crash khi startup
    • Log in ra panic: reached unreachable code rồi thoát
    • Nguyên nhân là lỗi kiểm tra sector padding
  • Checksum của TigerBeetle bao phủ dữ liệu của chunk nhưng loại trừ padding
    • Nếu bit 0 trong padding bị đổi thành 1, checksum vẫn pass
    • Sau đó assertion kiểm tra padding vẫn là 0 thất bại, khiến server crash
    • Hỏng padding không làm suy yếu safety và có thể được đưa về 0 hoặc khôi phục từ replica khác
  • VOPR trước đây không tìm thấy lỗi này vì nó làm hỏng toàn bộ sector
    • Hỏng sector kích hoạt đường dẫn checksum failure và repair, nên không đi tới assertion padding
    • TigerBeetle đã thêm single-byte error vào VOPR trong #2681
    • Từ 0.16.26, sector bị hỏng padding được repair thay vì làm crash
  • Bit flip ở copy number của superblock cũng có thể gây ra panic tương tự
    • Bốn bản sao superblock có các số copy 2 byte khác nhau, và checksum bỏ qua số này
    • Sau khi copy number bị hỏng trên đĩa được đọc vào bộ nhớ, assertion phạm vi 0–3 thất bại khi write
    • Đã giải quyết trong 0.16.26 bằng cách reset copy number

Các vấn đề liên quan đến nâng cấp

  • Khi nâng cấp từ 0.16.25 trở xuống lên 0.16.26 trở lên, lỗi crash panic: checkpoint diverged được quan sát lặp lại
    • Nguyên nhân là thay đổi cấu trúc CheckpointState trong 0.16.26
    • Phiên bản mới bao gồm tập hợp released blocks, nhưng thông tin này có thể trống trong quá trình truyền trạng thái tương thích với phiên bản cũ
    • Sau đó, khi một node khởi động lại bằng 0.16.26, nó có thể rơi vào trạng thái đã mất các released blocks mà những replica khác biết
    • Assertion phát hiện divergence và crash, ngăn client quan sát dữ liệu không nhất quán
  • Vấn đề này được ghi lại trong changelog qua #2745
    • TigerBeetle không phát hành bản 0.16.26 đã vá
    • Operator cần dừng client và chờ replica catch-up trước khi nâng cấp lên 0.16.26 trở lên
  • Khi thực hiện liên tiếp nhiều lần upgrade từ 0.16.16 lên 0.16.28 trong khoảng 20 giây, hoặc khi node bị pause/crash trong lúc upgrade, lỗi assertion release_transition xảy ra
    • Node đang chạy mở binary mới bằng memfd và thay thế bằng exec(), nhưng trong khoảng thời gian đó binary trên đĩa có thể đã bị thay bằng phiên bản mới hơn nữa
    • Code assert rằng cả version header trên đĩa cũng giống với phiên bản đang chạy hiện tại, dẫn đến thất bại
    • #2758 đã đổi assertion này thành warning trong 0.16.29
  • Khi nâng cấp từ 0.16.26 lên 0.16.27, panic: switch on corrupt value xảy ra do deprecated message type
    • Câu lệnh switch của node mới không có case cho kiểu message cũ nên crash
    • #2763 đã sửa trong 0.16.29 bằng cách đưa deprecated message type trở lại vào case và bỏ qua nó

Khôi phục khi mất đĩa ở một node đơn lẻ

  • TigerBeetle chịu lỗi tốt trước hỏng file, nhưng toàn bộ file dữ liệu của node có thể biến mất hoặc bị hỏng không thể khôi phục do lỗi đĩa, hỏa hoạn, lỗi EBS volume, sai sót của operator, v.v.
  • Tại thời điểm báo cáo, tài liệu chưa có cách thay thế node lỗi; một quy trình khôi phục chưa được document là chạy tigerbeetle format để khởi tạo bằng file dữ liệu trống rồi kỳ vọng repair
  • Jepsen xác nhận rằng reformat phần lớn hoạt động, nhưng có thể không an toàn
    • Nếu trong 3 node có 2 node chứa committed operation op và một trong số đó bị reformat, majority 2/3 chưa quan sát op có thể thực hiện view change khiến operation bị mất
    • Trong thử nghiệm thực tế, có một run bị mất 5 acknowledged transfer
    • Cũng có trường hợp trong quá trình upgrade, node được format bằng newer binary bị startup crash trước khi hoàn tất cluster version transition
  • Vấn đề này được theo dõi tại #2767
  • Sau đó, TigerBeetle 0.16.43 đã bao gồm lệnh tigerbeetle recover để khôi phục node gặp catastrophic data loss

Kết luận và khuyến nghị của Jepsen

  • Có hai vấn đề về an toàn được phát hiện
    • Thiếu kết quả truy vấn nhiều bộ lọc trước 0.16.17
    • Timestamp sai và trùng lặp trong API debug của Java client dùng cho kiểm thử Jepsen
  • Tổng cộng có 7 vấn đề crash
    • 2 vấn đề Java client: truy cập uninitialized memory, process crash khi eviction
    • 5 vấn đề server: 2 panic liên quan đến hỏng đĩa, 3 panic liên quan đến nâng cấp
    • #2745 đã được document, còn các crash còn lại đã được giải quyết đến 0.16.29
  • 0.16.43 giải quyết tất cả trừ một trong các issue của báo cáo
    • Mục chưa được giải quyết là việc client request tiếp tục retry theo thiết kế
  • Khuyến nghị cho người dùng rất rõ ràng
    • Nâng cấp lên 0.16.43
    • Kiểm tra release note khi chuyển lên 0.16.26 hoặc các phiên bản sau đó
    • Mô phỏng lỗi một node trong môi trường thử nghiệm và đo cách ứng dụng phản ứng với latency tăng lên
  • Kiến trúc của TigerBeetle có vẻ sound, và việc tích hợp VR, flexible quorum, protocol-aware recovery được quan sát là không làm tổn hại các bất biến cốt lõi của Strong Serializability
  • Tuy nhiên, kiểm chứng của Jepsen là một cách tiếp cận thực nghiệm, nên có thể chứng minh sự tồn tại của bug nhưng không thể chứng minh chúng vắng mặt

1 bình luận

 
GN⁺ 2025-06-07
Các ý kiến trên Hacker News
  • Bài nên đọc kèm: Fuzzer Blind Spots (Meet Jepsen!) – https://tigerbeetle.com/blog/2025-06-06-fuzzer-blind-spots-m...

  • Báo cáo này thật sự ấn tượng. Mỗi khi thấy TigerBeetle tuyên bố về độ tin cậy và khả năng mở rộng, tôi đều nghĩ “được rồi, chờ báo cáo Jepsen xem sao”
    Báo cáo nêu ra một số vấn đề và có thể khiến người ta lo ngại, nhưng điểm tích cực là họ không chỉ sửa xong rồi thôi, mà còn mở rộng bộ kiểm thử nội bộ để bắt các lỗi tương tự trong tương lai. Với cách tiếp cận kỹ thuật như thế này, 10 năm nữa TigerBeetle có thể trở thành cơ sở dữ liệu mặc định kiểu “cứ dùng Postgres là được” trong ngách ứng dụng tài chính
    Công việc của aphyr cũng rất xuất sắc, đọc báo cáo xong cảm giác học được rất nhiều

    • TigerBeetle có hơn 6.000 assertion, và một số assertion chặt đến mức gây crash, nhưng chúng đã làm đúng vai trò của mình: báo hiệu rằng mental model cần được điều chỉnh, và thực tế họ đã điều chỉnh
      Ngoài ra, trừ một lỗi đúng đắn nhỏ trong tính năng kiểm thử nội bộ chỉ được thêm vào Java client để hỗ trợ việc audit Jepsen, Jepsen chỉ tìm thấy một lỗi đúng đắn duy nhất và lỗi đó không ảnh hưởng đến độ bền dữ liệu. Bài liên quan ở đây: https://tigerbeetle.com/blog/2025-06-06-fuzzer-blind-spots-m...
      Nói công bằng thì TigerBeetle được thiết kế và kiểm thử để chịu được nhiều loại lỗi hơn Postgres. Lý do là nó có mô hình lỗi lưu trữ rõ ràng và tận dụng các nghiên cứu chưa tồn tại vào thời điểm Postgres ra đời năm 1996. Mô hình lỗi của TB còn được kiểm chứng bổ sung bằng deterministic simulation testing, và cũng dùng các kỹ thuật như cấp phát bộ nhớ tĩnh theo Power of Ten Rules của NASA dành cho Safety-Critical Code. Trong tài liệu có những kịch bản đã biết khiến Postgres mất dữ liệu, nhưng TigerBeetle có thể phát hiện và khôi phục chúng
      Muốn xem thêm thì hãy đọc phần helical fault injection trong báo cáo của Kyle. Phần lớn các triển khai Raft và Paxos không được thiết kế để chịu được điều này, và cũng có bài trình bày ở QCon London: https://m.youtube.com/watch?v=_jfOk4L7CiY
    • Tôi luôn mong chờ các bài viết của Kyle. Mỗi khi có bài mới, cảm giác như kiến thức về hệ thống phân tán lại tăng thêm một bậc
  • Thật vui khi thấy qua kiểm chứng của aphyr, TigerBeetle thể hiện đúng với những gì họ tuyên bố. Thật tốt khi thấy chọn đúng cách tiếp cận thì sẽ cho ra kết quả đúng
    Tôi tò mò TigerBeetle sẽ được dùng trong thực tế như thế nào. Chắc sẽ có nhiều hệ thống bên ngoài và cơ sở dữ liệu khác xung quanh một cài đặt TigerBeetle để phục vụ mọi thứ không phải Account hay Transfer; vậy mô hình điển hình để các hệ thống kém tin cậy hơn đó phối hợp với TigerBeetle là gì, đặc biệt là khi có vấn đề nhất quán giữa hai bên thì khôi phục ra sao?

    • Mô hình điển hình khi tích hợp TigerBeetle là tách control planedata plane. Dùng Postgres cho mục đích tổng quát hoặc OLGP, và dùng TigerBeetle cho xử lý giao dịch hoặc OLTP
      Thông tin người dùng (tên, địa chỉ, mật khẩu, v.v.) và thông tin sản phẩm (mô tả, giá, v.v.) được đưa vào OLGP như một “tủ hồ sơ”
      Còn mọi giao dịch vào Black Friday, khi người dùng chuyển sản phẩm từ tài khoản tồn kho sang tài khoản giỏ hàng, rồi sang tài khoản thanh toán và giao hàng, thì đưa vào OLTP như một “két sắt”. TigerBeetle cho phép lưu tối đa 3 định danh dữ liệu người dùng trên mỗi account hoặc transfer, nhờ đó có thể liên kết sự kiện giữa các thực thể với cơ sở dữ liệu OLGP mô tả các thực thể đó
      Kiến trúc này [1] đem lại phân tách mối quan tâm rõ ràng, cho phép mở rộng và quản lý độc lập các workload khác nhau. Nếu là ngân hàng, thay vì giữ toàn bộ tiền mặt trong tủ hồ sơ chứa hồ sơ khách hàng, sẽ hợp lý hơn khi giữ tiền mặt trong két sắt, vì nó có đặc tính về hiệu năng, tuân thủ và lưu giữ khác biệt
      Mẫu này phù hợp vì tần suất người dùng đổi tên hoặc địa chỉ email (OLGP) thấp hơn rất nhiều so với tần suất họ giao dịch (OLTP)
      Để bảo toàn tính nhất quán, trên write path hãy xem TigerBeetle là OLTP data plane và là “nguồn sự thật”. Khi có giao dịch “chuyển vào giỏ hàng” hoặc “thanh toán”, trước tiên ghi các phụ thuộc dữ liệu cần thiết vào OLGP, nếu có dữ liệu blob liên quan thì cũng ghi vào nơi như S3, rồi cuối cùng ghi vào TigerBeetle để commit giao dịch. Trên read path, truy vấn nguồn sự thật trước để bảo toàn tính serializable nghiêm ngặt
      [1] https://docs.tigerbeetle.com/coding/system-architecture/
  • Sau khi đọc bài về các điểm mù của fuzzer trong TigerBeetle, đây là một báo cáo Jepsen đặc biệt thú vị
    Segfault ở phía JNI có vẻ như Rust hay một ngôn ngữ an toàn bộ nhớ khác cũng không ngăn được. Việc gần như không có lỗi an toàn bộ nhớ là bằng chứng cho thấy cách lập trình bằng Zig của TigerBeetle, nếu nhớ không nhầm là TigerStyle, đã làm khá tốt vai trò mà nó được kỳ vọng

    • Xem https://news.ycombinator.com/item?id=44201189. Đúng là có một lỗi mà nếu dùng Rust thì đã cứu được. Nhưng assertion đã cứu thay, nên miếng bacon chỉ hơi giòn chứ chưa bị cháy
      Dù vậy vẫn đúng. Nếu không có TigerStyle thì hẳn đã bị nasal demons xử rồi
  • Tôi thích bản báo cáo cực kỳ chi tiết này. Việc Jepsen đã kiểm thử và ký xác nhận là một sự bảo chứng rất lớn cho TigerBeetle. Nó còn chưa đạt tới v1.0, nên tôi rất mong chờ các cột mốc mới sắp tới
    Cũng xin đặc biệt tán dương các nhà sáng lập đã chia sẻ những góc nhìn hay trong luồng này

    • Kyle đã làm một việc đáng kinh ngạc, và mức độ chi tiết trong báo cáo cũng thật sự tuyệt. Trong lúc đọc, tôi đã nghĩ “cái này giống một tác phẩm nghệ thuật”, cảm nhận được sự thủ công tinh xảo và độ chính xác
      Tôi cũng rất mong phần trình bày SD25 sắp tới ở Amsterdam, nơi sẽ chia sẻ thêm nội dung mới
  • Tôi hơi thích cái tiêu đề mục “Panic! At the Disk 0”

  • Nhìn lại thì có vẻ hiển nhiên nhưng vẫn thú vị: hệ thống phân tán được kiểm thử phải báo cáo thời gian và thứ tự mà sự việc thực sự xảy ra, để có thể kiểm chứng chính xác với mô hình bên ngoài của hệ thống thay vì dùng thời gian đồng hồ treo tường

    • Điều này hoạt động được là nhờ có strict serializability. Với các bảo đảm nhất quán yếu hơn, không nhất thiết tồn tại một timeline nhất quán toàn cục duy nhất
      Đây là một mẫu meta thú vị: khi làm được việc khó hơn, hệ thống lại trở nên đơn giản hơn
      Một ví dụ khác: vì giả định đĩa có thể hỏng và phải có giao thức khôi phục, ta gần như có được việc đồng bộ trạng thái cho các bản sao tụt hậu “miễn phí”, bởi đó chính xác là cùng một vấn đề với tình huống toàn bộ đĩa bị hỏng
    • Tôi nghĩ đây là cách tiếp cận kinh điển. Ví dụ: https://lamport.azurewebsites.net/pubs/time-clocks.pdf
  • Trong bài, liên kết tới bài báo “Viewstamped Replication” tiếc là bị hỏng. https://pmg.csail.mit.edu/papers/vr-revisited.pdf bị từ chối kết nối
    Có lẽ phải dùng scheme http thay vì https, như http://pmg.csail.mit.edu/papers/vr-revisited.pdf
    Giờ thì tôi đã có thứ để đọc tối thứ Sáu rồi

    • Sẽ sớm được sửa
      Bài báo VSR 2012 là một trong những bài tôi thích nhất, và “Protocol-Aware Recovery for Consensus-Based Storage” cũng thật sự rất mạnh
      Chúc đọc vui
  • Đây là câu hỏi hoàn toàn vì muốn học hỏi, mong đừng bị hiểu nhầm. Tôi mới học về hệ thống phân tán và bị cuốn hút bởi kiểm thử mô phỏng tất định
    Sau khi xem qua báo cáo Jepsen về TigerBeetle, bài blog liên quan, và mã tích hợp Antithesis trong workflow GitHub, tôi muốn hiểu rõ hơn phạm vi kiểm thử
    Câu hỏi cốt lõi là liệu phần tích hợp Antithesis cũng có thể tìm ra những lỗi mà bộ kiểm thử Jepsen đã phát hiện hay không
    Câu hỏi này xuất phát từ vài giả định, có thể là sai. Tôi từng nghĩ TigerBeetle đã được kiểm thử toàn diện bằng bộ kiểm thử nội bộ và sản phẩm Antithesis, và hiểu rằng bộ kiểm thử Antithesis mạnh hơn Jepsen, nên tôi thấy bất ngờ khi Jepsen phát hiện vấn đề mà Antithesis không tìm ra
    Tôi muốn biết mình hiểu sai ở đâu. Chẳng hạn, tôi muốn biết 1) bộ kiểm thử Antithesis không thể phát hiện lớp lỗi cụ thể này, 2) phần này của hệ thống chưa được kiểm thử bằng Antithesis, hay 3) tôi đang hiểu sai các điểm mạnh và mục tiêu khác nhau của bộ kiểm thử Jepsen và Antithesis, tức là đang so sánh táo với cam

    • Bài blog của TigerBeetle nói chi tiết hơn, nhưng tóm lại, các bài kiểm thử chạy trên Antithesis tuy khá kỹ lưỡng nhưng đã không tạo ra đúng tổ hợp giữa các truy vấn giao nhaucác giá trị bị đảo thứ tự, còn trình sinh của Jepsen đã trúng tổ hợp đó
      Gần như chắc chắn trình sinh kiểm thử của Jepsen cũng có điểm mù. Đó là lý do thiết kế nhiều trình sinh khác nhau lại hữu ích
    • Kiểm thử sinh cho hệ thống phân tán thường cần ba thành phần. Thứ nhất, cần một môi trường để chạy hệ thống. Đơn giản nhất là dựng một cụm máy thật, nhưng nếu muốn tăng hiệu năng, kiểm soát phản hồi API bên ngoài, tính tất định và khả năng tái hiện, thì nên dùng thứ tinh vi hơn. Thứ hai, cần một trình sinh tải để khiến hệ thống trong môi trường đó làm những việc thú vị. Thứ ba, cần một bộ kiểm toán quan sát hành vi của hệ thống dưới tải và phán định xem có khớp đặc tả không
      Antithesis chủ yếu xử lý vấn đề số 1, cung cấp môi trường mô phỏng tất định bằng máy ảo. Jepsen xử lý cùng vấn đề này bằng cách dùng máy thật nhưng tiêm lỗi ở cấp hệ điều hành, còn VOPR nội bộ của TigerBeetle được thiết kế cùng với cơ sở dữ liệu, cho phép chạy cả cụm trong một luồng duy nhất. Ba cách tiếp cận này bổ trợ cho nhau và mỗi cách có những lĩnh vực thế mạnh riêng
      Phần mang tính quyết định trong lỗi này là số 2 và 3, tức là viết workload validator và auditor có thể thật sự kích hoạt lỗi. Ở đây, 1.600 dòng mã Clojure chuyên biệt cho TigerBeetle do aphyr viết đã kích hoạt và phát hiện lỗi, sau đó bài kiểm thử tương đương phía TigerBeetle cũng được vá để kích hoạt lỗi này. Thật ra, thứ có lỗi ở đây không hẳn là cơ sở dữ liệu mà là VOPR. Cơ sở dữ liệu có lỗi là chuyện đương nhiên, và không thể tránh lỗi chỉ bằng ý chí. Vì vậy cần một chiến lược kiểm thử có thể kích hoạt phần lớn lỗi, và những lỗi lọt qua chỉ ra khiếm khuyết của trình sinh workload
    • 90% kiểm thử mô phỏng tất định chủ yếu do trình mô phỏng tất định VOPR mà TigerBeetle tự xây dựng thực hiện. Nó chạy 24/7 trên quy mô 1.000 lõi CPU chuyên dụng
      Chúng tôi cũng dùng Antithesis, nhưng dùng như lớp thứ hai của kiểm thử mô phỏng tất định
      Xem ở đây để biết vì sao lỗi query engine đã lọt qua: https://tigerbeetle.com/blog/2025-06-06-fuzzer-blind-spots-m...
  • Thắc mắc liệu các ngân hàng lớn hay sàn giao dịch chứng khoán có dùng TigerBeetle hay không

    • Ở cấp quốc gia, họ đang cùng Gates Foundation tích hợp TigerBeetle vào một switch ngân hàng trung ương phi lợi nhuận, và hệ thống này dự kiến sẽ vận hành National Digital Payments System 2.0 của Rwanda vào cuối năm nay [1]
      Ở cấp doanh nghiệp, TigerBeetle đã được dùng trong production bởi các khách hàng xử lý hơn 100 triệu giao dịch mỗi tháng; gần đây họ đã ký hợp đồng đầu tiên với một kỳ lân fintech châu Âu trị giá 2 tỷ USD, và một vài thương vụ ở Mỹ cũng sắp hoàn tất. Do xu hướng trên toàn cầu chuyển sang xử lý giao dịch thời gian thực [2], khá nhiều công ty quan tâm đến việc chuyển sang TigerBeetle để đạt hiệu năng cao hơn
      Để trả lời câu hỏi, một số nhà sáng lập của Clear Street, một công ty môi giới khá lớn ở Wall Street, đã đầu tư vào TigerBeetle [3]
      [1] https://mojaloop.io/how-mojaloop-enables-rndps-2-0-ekash/
      [2] https://tigerbeetle.com/blog/2024-07-23-rediscovering-transa...
      [3] https://tigerbeetle.com/company
    • Không phải ngân hàng hay sàn giao dịch, nhưng tôi đang làm ở một công ty fintech rất lớn và đang dùng TigerBeetle cho sản phẩm mới
    • Nếu có khách hàng như vậy thì chắc họ đã khoe trên trang chủ rồi. Cho đến giờ, sự bảo chứng lớn nhất trên trang chủ đến từ một YouTuber nào đó. Đúng là một YouTuber nổi tiếng, nhưng dù sao vẫn là YouTuber