1 điểm bởi GN⁺ 2025-06-07 | 1 bình luận | Chia sẻ qua WhatsApp
  • TigerBeetle là cơ sở dữ liệu OLTP chuyên cho kế toán bút toán kép, được phát triển với mục tiêu an toàn và tốc độ xử lý cao
  • Hỗ trợ giao thức đồng thuận Viewstamped Replication và tiêu chí strong serializability, với kiến trúc tối ưu cho khối lượng công việc có mức tranh chấp cao và thông lượng lớn
  • Có thiết kế và quy trình kiểm thử đặc biệt chú trọng khả năng chịu lỗi và phục hồi sau sự cố, hướng tới vận hành không mất dữ liệu trong nhiều tình huống lỗi khác nhau
  • Jepsen đã phát hiện nhiều lỗi và vấn đề hiệu năng trong nâng cấp, kiểm thử, mô hình vận hành và khả năng phục hồi của cụm, qua đó cải thiện khả năng ứng phó
  • Ở phiên bản mới nhất, có nhiều cải tiến và bản sửa lỗi liên quan đến hiệu năng sao chép dựa trên Ring, xử lý lỗi phía client, độ chính xác của logging và truy vấn

Giới thiệu TigerBeetle

  • TigerBeetle là cơ sở dữ liệu xử lý giao dịch trực tuyến (OLTP) chuyên cho kế toán bút toán kép (Double-entry bookkeeping)
  • Bảo đảm strong serializability dựa trên giao thức đồng thuận Viewstamped Replication (VR), và chỉ lưu dữ liệu tài khoản cùng dữ liệu chuyển khoản giữa các tài khoản
  • Phù hợp với các môi trường có khối lượng giao dịch lớn và mức cạnh tranh đồng thời cao như switching nội bộ ngân hàng, môi giới, phát hành vé, đo đếm điện năng
  • Có kiến trúc trong đó một node (Core) duy nhất đảm trách toàn bộ thao tác ghi, nên tập trung vào mở rộng theo chiều dọc (Scale-up) thay vì mở rộng ngang (Scale-out)
  • Hướng tới tối đa hóa thông lượng trên một node đơn thông qua các tối ưu thân thiện với phần cứng như xử lý theo lô, song song hóa IO và schema cố định

Khả năng phục hồi và chịu lỗi

  • TigerBeetle cung cấp mô hình tường minh và quy trình khôi phục cho các lỗi về bộ nhớ, tiến trình, đồng hồ, lưu trữ và mạng
  • Độ bền dữ liệu được bảo đảm không mất dữ liệu chỉ cần còn duy nhất một bản sao sống
    • Nếu bản ghi trên mọi bản sao đều bị hỏng thì hệ thống sẽ dừng an toàn
  • Giả định nhiều loại sự cố như lỗi phần cứng/phần mềm hệ thống, sai lệch đồng hồ, hỏng đĩa, độ trễ/mất mát/trùng lặp mạng
  • Áp dụng Viewstamped Replication, kỹ thuật Protocol-Aware Recovery, checksum cho khối dữ liệu và lưu trữ trên nhiều bản sao
  • Sử dụng kiểm chứng khi chạy (assertion) để giảm thiểu thiệt hại khi xảy ra lỗi hoặc bug

Cách thức nâng cấp

  • Binary bao gồm mã của phiên bản hiện tại và nhiều phiên bản trước đó
  • Việc nâng cấp có thể thực hiện chỉ bằng cách thay binary
  • Tất cả node trong cụm tự động đổi phiên bản theo kiểu rolling, giảm tối đa can thiệp của người dùng
  • Ngăn việc một thao tác đã commit ở phiên bản này bị commit trùng lặp ở phiên bản khác, nhờ đó có lợi cho việc tránh sai lệch trạng thái

Mô hình thời gian

  • Đồng thời sử dụng đồng hồ logic dựa trên VR view và số thứ tự thao tác, cùng đồng hồ vật lý lai (physical time)
  • Leader thu thập thời gian POSIX của mọi bản sao và đồng bộ lẫn nhau trong phạm vi sai số cho phép trong cụm
  • Nếu việc đồng bộ đồng hồ thất bại quá 60 giây thì từ chối phục vụ
  • Timestamp dùng đơn vị "nanosecond kể từ Unix epoch" nhưng lệch 27 giây so với thời gian POSIX thực tế
  • Khi có leap second hoặc điều chỉnh thời gian âm, đồng hồ nội bộ có thể chạy chậm lại

Mô hình dữ liệu

  • Chỉ hỗ trợ hai kiểu dữ liệu là tài khoản (account)chuyển khoản (transfer)
    • Mỗi trường có kích thước cố định, tuân theo nguyên tắc bất biến (immutable), và được thiết kế dựa trên unsigned int
  • Tài khoản được định nghĩa bằng id 128-bit do người dùng tự đặt, ledger, flag, thời điểm tạo và các trường tùy biến
  • Chuyển khoản bao gồm debit/credit account id, code, amount, các trường tùy biến, v.v.
  • Hỗ trợ cả thực thi ngay (một bước) lẫn xử lý hai bước (đặt trước/thương lượng thực thi) cho chuyển khoản
    • Có thể hủy hoặc hết hạn chuyển khoản đặt trước (pending)
    • Có thể dùng chuyển khoản đặc biệt để đóng/mở lại tài khoản

Mô hình vận hành và giao dịch

  • Client hoạt động theo đơn vị một request (batch) để cập nhật hoặc truy vấn trạng thái dữ liệu
  • Mỗi sự kiện trong request được xử lý tuần tự như một giao dịch nguyên tử (atomic)
  • Không hỗ trợ chạy lặp lại, giao dịch nhiều request hay truy vấn tương tác
  • Cung cấp Strong Serializability và tính nhất quán phiên mạnh
  • Hỗ trợ xử lý phức hợp thông qua kết quả thành công/thất bại, mã lỗi trả về và tính năng chain (chuỗi, subtransaction)

Thiết kế kiểm thử Jepsen

  • Thực hiện kiểm thử dựa trên thuộc tính (property-based)tiêm lỗi (fault injection) thông qua thư viện Jepsen
  • Thử nghiệm trên cụm 3~6 node trong nhiều môi trường như LXC, EC2
  • Do ràng buộc của mô hình dữ liệu nên khó kiểm chứng tính nhất quán theo kiểu list/set truyền thống → dùng toàn bộ thứ tự thao tác (total order) để kiểm tra tính nhất quán của trạng thái/thời gian
  • Phát hiện lỗi bằng các cách bổ sung cho nhau như kiểm tra nhất quán dựa trên timestamp, kiểm chứng mô hình, mô phỏng

Kiểm chứng mô hình và sinh thao tác

  • Kiểm tra rất chi tiết tính đúng đắn của TigerBeetle bằng mô hình state machine đơn luồng dài hơn 1600 dòng
  • Xử lý suy luận và rollback cho nhiều điều kiện lỗi khác nhau như id trùng, timestamp không liên tục, ràng buộc số dư và linked chain
  • Để tăng hiệu quả kiểm chứng, sử dụng nhiều cách như sinh operation·id, cập nhật trạng thái, kết hợp truy vấn theo xác suất

Tiêm lỗi

  • Bao gồm các kịch bản lỗi cơ bản như crash tiến trình (SIGKILL), tạm dừng (SIGSTOP), phân vùng mạng, thay đổi đồng hồ
  • Tiêm lỗi lưu trữ tinh vi như nâng cấp phiên bản, mô phỏng hỏng file, hỏng cục bộ chỉ ở một số bản sao
  • Xác minh khả năng giảm thiểu mất dữ liệu với nhiều kịch bản như hỏng đĩa ziczac (helical)

Các lỗi tiêu biểu và nội dung cải tiến

Vấn đề trong xử lý timeout request (#206)

  • Theo thiết kế của TigerBeetle, request từ client không bao giờ timeout; hệ thống retry vô hạn cho tới khi nhận được phản hồi từ cụm
  • Trên thực tế, client như Java có thể phát sinh ngoại lệ timeout khi thao tác bất đồng bộ, và ứng dụng rốt cuộc vẫn phải đặt timeout bên ngoài
  • Thiết kế này làm che mờ giữa lỗi mạng hoặc lỗi chắc chắn với trạng thái mơ hồ, khiến khó phân biệt thất bại rõ ràng và lỗi không chắc chắn
  • Jepsen khuyến nghị bổ sung cách trả về theo từng kiểu thất bại (chắc chắn/không chắc chắn) và tùy chọn retry

JVM crash do lỗi client (#2435)

  • Việc bọc bằng thread/bất đồng bộ để lách timeout đã gây ra vấn đề JVM segfault
  • Nguyên nhân là tham chiếu tới trường chưa được khởi tạo đúng cách trong Java client, đã được sửa ở 0.16.12

Client crash khi session hết hạn (#2484)

  • Hiện tượng client bị buộc dừng do session quá nhiều
  • Từ 0.16.13, đã được cải thiện thành cơ chế trả về lỗi

Độ trễ tăng vọt khi lỗi một node đơn lẻ (#2739)

  • Điểm yếu của cách sao chép dựa trên ring khiến thời gian phản hồi toàn hệ thống tăng mạnh khi một số node gặp lỗi
  • Nguyên nhân: mặc định primary gửi message từng bước tới node tiếp theo; khi một số node lỗi, việc không nhận được ack gây chờ đợi
  • Từ 0.16.30 trở đi, đã áp dụng sao chép ngược chiều và topo ring động, giúp cải thiện đáng kể độ trễ phản hồi khi có sự cố

Bug ở Header API của Java client (#2495)

  • Việc dùng singleton object cho batch phản hồi rỗng gây ra vấn đề chia sẻ sai header và timestamp
  • Không ảnh hưởng đến độ chính xác dữ liệu nhưng làm sai lệch kết quả của Header API, đã sửa ở 0.16.14

Thiếu kết quả truy vấn (#2544)

  • Ở phiên bản 0.16.13, có báo cáo bug làm query_accounts, query_transfers và các truy vấn khác bị thiếu một phần kết quả; kết quả trả về chỉ bị giới hạn ở prefix đúng

Kết luận

  • TigerBeetle được chuyên biệt cho các môi trường trong lĩnh vực tài chính và kế toán đòi hỏi độ an toàn cao cùng khả năng chịu lỗi mạnh
  • Chuỗi kiểm thử Jepsen đã làm lộ ra nhiều vấn đề về khả năng phục hồi, tính nhất quán, mô hình vận hành và hiệu năng
  • Thông qua hợp tác tích cực, đã đạt được những cải tiến thực chất về phục hồi sự cố, xử lý lỗi phía client, sao chép và tự động hóa nâng cấp
  • Ở phiên bản mới nhất, hệ thống mang lại mức độ tin cậy cao hơn với khả năng ứng phó sự cố vững chắc, bảo đảm kết nối/phản hồi và tính nhất quán của thao tác

(Một phần nội dung này được biên soạn có tham khảo nhiều nguồn mở như Github, tài liệu chính thức của TigerBeetle và báo cáo kiểm thử Jepsen)

1 bình luận

 
GN⁺ 2025-06-07
Ý kiến trên Hacker News
  • Bài Fuzzer Blind Spots (Gặp Jepsen!) cũng là thông tin tham khảo, có giới thiệu tại https://tigerbeetle.com/blog/2025-06-06-fuzzer-blind-spots-meet-jepsen/

  • Chia sẻ rằng mỗi khi nghe nói về độ tin cậy và khả năng mở rộng của TigerBeetle thì luôn chờ xác nhận cuối cùng từ báo cáo Jepsen; đánh giá cao việc báo cáo lần này phát hiện nhiều vấn đề, đội ngũ đã sửa rất nhanh và còn tăng cường test suite nội bộ để tránh lặp lại các bug tương tự trong tương lai. Với thái độ này, kỳ vọng trong 10 năm nữa TigerBeetle có thể trở thành lựa chọn mặc định kiểu “cứ dùng Postgres đi” trong mảng cơ sở dữ liệu chuyên cho tài chính. Cũng xác nhận đã học được rất nhiều nhờ công việc xuất sắc của aphyr

    • TigerBeetle có hơn 6.000 assertion; một số quá nghiêm nên từng gây ra vài crash, nhưng cũng nhờ đó các assertion đã thực hiện đúng vai trò cảnh báo như chủ đích. Trên thực tế, Jepsen chỉ tìm ra một bug correctness nhỏ trong tính năng test nội bộ phục vụ việc kiểm toán Jepsen phía Java client, cùng một bug correctness khác không ảnh hưởng đến durability. Trường hợp liên quan được giải thích chi tiết tại liên kết này. TigerBeetle đang được thiết kế và kiểm thử để chịu được nhiều dạng lỗi hơn Postgres, áp dụng mô hình lỗi lưu trữ tường minh, phản ánh các thành quả nghiên cứu chưa tồn tại vào thời Postgres ra mắt, dùng Deterministic Simulation Testing và tiêu chuẩn mã an toàn của NASA để đảm bảo ổn định theo nhiều lớp. Thậm chí với những kịch bản mất dữ liệu đã được ghi nhận rõ trong tài liệu về Postgres, TigerBeetle có thể phát hiện và khôi phục. Muốn biết thêm chi tiết thì nên xem phần helical fault injection của Kyle hoặc video bài nói chuyện tại QCon London ở đây
    • Mỗi lần đọc báo cáo của Kyle lại có cảm giác kỹ năng về hệ thống phân tán tăng thêm một bậc
  • Bày tỏ vui mừng khi TigerBeetle được aphyr kiểm chứng và đúng là giữ lời hứa, hy vọng rằng cách tiếp cận đúng có thể dẫn tới kết quả đúng. Đồng thời hỏi rằng trong thực tế, ngoài Account hay Transfer thì nhiều dữ liệu thường nằm ở hệ thống ngoài và cơ sở dữ liệu riêng; vậy vấn đề consistency và khôi phục giữa những hệ thống ngoài kém tin cậy đó với TigerBeetle thực tế được xử lý như thế nào

    • Zoran của TigerBeetle giải thích về các mẫu tích hợp: nhìn chung khuyến nghị kiến trúc tách riêng control plane (OLGP thông thường, ví dụ Postgres) và data plane (OLTP, ví dụ TigerBeetle). Dữ liệu như thông tin người dùng nằm trong OLGP như một “tủ hồ sơ”, còn dữ liệu giao dịch (tồn kho → giỏ hàng → thanh toán, v.v.) nằm trong OLTP như một “két sắt”, mỗi bên đảm nhận vai trò riêng. Với mỗi account hoặc transfer có thể gắn tối đa 3 định danh dữ liệu người dùng để liên kết thực thể và sự kiện bên OLGP. Cách tách này mang lại lợi thế về mở rộng quy mô, vận hành và quản trị độc lập. Ví dụ như ngân hàng, việc tách tiền mặt (két sắt) và thông tin (tủ hồ sơ) là rất phù hợp. Vì tần suất giao dịch thực tế và tần suất thay đổi thông tin như tên/email là khác nhau nên cấu trúc này là hợp lý. Để đảm bảo nhất quán dữ liệu, ở đường ghi nên ghi dữ liệu phụ thuộc vào OLGP (và các kho ngoài cần thiết như S3) trước, rồi commit vào TigerBeetle ở bước cuối. Ở đường đọc thì luôn truy vấn TigerBeetle như source of record, từ đó đạt được độ tin cậy nhờ strict serializability. Có đính kèm tài liệu kiến trúc
  • Có ý kiến rằng nếu đã đọc bài về fuzzer blind spot của Jepsen thì báo cáo TigerBeetle lần này còn thú vị hơn nhiều. Trường hợp segfault phía JNI có thể cũng không được bảo vệ chỉ bằng việc dùng ngôn ngữ an toàn bộ nhớ như Rust, nhưng cách tiếp cận Zig/TigerStyle của TigerBeetle được xem là một minh chứng tốt về an toàn bộ nhớ

    • Chia sẻ từng gặp một bug mà Rust cũng có thể phòng được; trên thực tế phần lớn đã bị assertion chặn lại, và nếu không có TigerStyle thì tình huống có thể còn nguy hiểm hơn
  • Tán thưởng nhẹ về độ dí dỏm của tiêu đề phần "Panic! At the Disk 0"

  • Bày tỏ ấn tượng sâu sắc với báo cáo chi tiết đã được Jepsen xác nhận; dù vẫn chưa phát hành v1.0 nhưng mức kỳ vọng đã rất cao. Cũng khen riêng việc các nhà sáng lập tích cực chia sẻ insight trong thread

    • Còn về sự tỉ mỉ của Kyle và độ tinh xảo gần như nghệ thuật của bản báo cáo, cũng mong chờ tin về bài trình bày mới tại SD25 Amsterdam
  • Cảm nhận rằng trong kiểm thử hệ thống phân tán, việc chính hệ thống tự báo cáo thứ tự/thời gian phát sinh bên trong để đối chiếu chính xác với mô hình bên ngoài là điều kiện thiết yếu cho việc kiểm chứng chính xác, và thấy điều đó “rõ ràng đến mức hiển nhiên” thật thú vị

    • Trong môi trường strict serializability thì cách này khả thi, còn với các mức đảm bảo nhất quán yếu hơn thì không thể có một timeline toàn cục duy nhất. Cũng thấy thú vị ở mẫu meta là đưa vào một bài toán khó lại có thể làm hệ thống đơn giản hơn; ví dụ nếu bổ sung giao thức lỗi/khôi phục đĩa làm nền tảng thì việc state sync cho replica chậm cũng gần như có được “miễn phí”
  • Sau khi xem báo cáo Jepsen, blog liên quan và mã tích hợp Antithesis, có người hỏi với mục đích học hỏi về phạm vi và hiệu quả của kiểm thử: trong TigerBeetle vốn đã có kiểm thử khá toàn diện bằng Antithesis, vậy tại sao bug mà Jepsen phát hiện lại không bị Antithesis bắt được? Cụ thể muốn hiểu sự khác nhau giữa Antithesis và kiểm thử Jepsen, cũng như rốt cuộc phạm vi kiểm thử nội bộ khác nhau thế nào

    • aphyr giải thích thêm rằng để làm generative testing cho hệ thống phân tán cần 3 thành phần: 1) môi trường chạy hệ thống 2) bộ sinh tải 3) auditor. Antithesis chủ yếu thuộc phần 1, tức cung cấp môi trường mô phỏng quyết định luận; Jepsen thì chèn lỗi ở mức máy thật và OS; còn VOPR của TigerBeetle vận hành toàn bộ cluster trong một thread. Mỗi kiểu mô phỏng đều có ưu và nhược riêng, bổ sung cho nhau. Trong trường hợp bug lần này thì cốt lõi lại nằm ở 2) và 3), tức workload generator và auditor dùng để kiểm chứng. Chính mã Clojure chuyên cho TigerBeetle của aphyr đã tạo ra và phát hiện bug đó; sau đó phía TigerBeetle cũng vá phần mã tương đương của mình. Hóa ra vấn đề cốt lõi còn nằm ở VOPR nhiều hơn là ở bản thân DB. Với cơ sở dữ liệu phân tán thì bug luôn có thể tồn tại, nên về căn bản điều quan trọng là thiết kế nhiều bộ sinh và chiến lược kiểm thử khác nhau
    • Blog của TigerBeetle cũng giải thích chi tiết vấn đề này: tóm lại, bài test dùng trong Antithesis không bao phủ điều kiện cross-query và giá trị out-of-order cần thiết để kích hoạt bug lần này, còn phía Jepsen lại có đúng tổ hợp đó nên phát hiện được. Đồng thời cũng nhấn mạnh rằng test generator của Jepsen cũng có giới hạn nhất định và cần nhiều thiết kế generator đa dạng
    • 90% kiểm thử mô phỏng độ trễ nội bộ được chạy bằng VOPR (trình mô phỏng riêng), vận hành 24/7 trên 1.000 lõi CPU; Antithesis được dùng như một lớp bổ sung. Về việc vì sao bug trong query engine lại lọt qua, có thể xem bài viết này
  • Nói rằng bản thân quan tâm đến TigerBeetle và thấy lạ khi trong tài liệu client không có client C hay Zig; hỏi liệu các client này là chưa tồn tại hay vẫn đang được phát triển, nhất là khi chính TigerBeetle được viết bằng Zig

  • Hỏi liệu TigerBeetle đã được dùng bởi các ngân hàng lớn hay công ty chứng khoán lớn hay chưa

    • Zoran của TigerBeetle cho biết hiện đang được dùng trong dự án xây dựng hệ thống thanh toán số quốc gia 2.0 và ngân hàng trung ương điện tử tại Luanda, hợp tác cùng Gates Foundation. Ở cấp doanh nghiệp, đã có khách hàng production xử lý hơn 100 triệu giao dịch mỗi tháng, gần đây cũng ký hợp đồng với một fintech unicorn châu Âu trị giá 2 tỷ USD, và tại Mỹ cũng đang có thêm các hợp đồng khác. Nhu cầu áp dụng TigerBeetle đang tăng lên toàn cầu nhờ nhu cầu xử lý giao dịch thời gian thực. Các nhà sáng lập của Clear Street, một công ty môi giới cỡ vừa đến lớn ở Wall Street, cũng đã tham gia đầu tư. Có kèm các liên kết liên quan: mojaloop.io, blog của TigerBeetle, giới thiệu công ty
    • Chưa phải ngân hàng hay sàn giao dịch lớn, nhưng bản thân đang dùng nó cho một sản phẩm mới tại một fintech lớn
    • Có ý kiến cho rằng vì họ không khoe trên trang chủ nên có thể không có các reference tên tuổi lớn; hiện tại endorsement lớn nhất có vẻ chỉ là sự giới thiệu từ một YouTuber có ảnh hưởng