Giaosucan's blog - Chia sẻ kiến thức theo cách bá đạo

Ticker

20/recent/ticker-posts

Cách Netflix build Distributed Write Ahead Log

Anh em nào làm việc với DB thì khái niệm Write-Ahead Log (WAL) chắc hẳn không xa lạ (vì nó là trái tim của Postgres, MySQL hay Spark Structured Streaming). Khi hệ thống thực hiện thao tác như INSERT, UPDATE, DELETE, nó sẽ không ghi trực tiếp vào database, mà sẽ được ghi vào WAL giống như nhật kí, sau đó mới được ghi xuống database, dựa vào cơ chế này mà chúng ta có thể tạo ra các bản replication dựa trên nhật kí WAL này.

image.png

Tại Netflix, WAL không chỉ đơn thuần là một file log của database. Nó được nâng tầm thành một kiến trúc phân tán (Distributed Event Store) để giải quyết bài toán: Làm sao để hàng nghìn Microservices đồng bộ dữ liệu với nhau mà không bị mất mát hay sai lệch?

Tại sao Netflix cần một WAL riêng?

Dual Write issue

Nextfix có hàng ngàn Microservices, khi một Service cập nhật Database (ví dụ: người dùng vừa thanh toán gói Premium), có hai việc phải xảy ra đồng thời:

Cập nhật vào DB chính (Postgres/Cassandra).

Thông báo cho các Service khác (Gửi Email, Cập nhật kho phim, Cập nhật Analytics).

Nếu DB cập nhật xong nhưng hệ thống nhắn tin (Kafka) bị lỗi, dữ liệu sẽ bị “vênh”, gọi là “Dual-write”
Nếu DB cập nhật thành công nhưng việc gửi tin nhắn đến Kafka thất bại, dữ liệu giữa các hệ thống sẽ bị vênh.
Giải pháp truyền thống là dùng Distributed Transactions (2PC) nhưng nó quá chậm và không thể mở rộng ở quy mô của Netflix.

"Entropy" trong hệ thống phân tán

Tại Netflix, mỗi hành động của người dùng thường kéo theo hàng loạt thay đổi dữ liệu ở nhiều nơi khác nhau. Nếu không có WAL, họ đối mặt với:

Mất dữ liệu: Một lỗi trong quá trình ALTER TABLE hoặc lỗi mạng có thể khiến dữ liệu bị hỏng vĩnh viễn nếu không có cơ chế ghi chép lại các bước thực hiện trước đó.

Không nhất quán (Inconsistency): Việc phải ghi đồng thời vào nhiều nơi (ví dụ: ghi vào Cassandra và cập nhật Elasticsearch) dễ dẫn đến tình trạng một nơi thành công, một nơi thất bại.

Quá tải hệ thống: Các tác vụ nặng như xóa hàng loạt (bulk delete) có thể làm sập cơ sở dữ liệu nếu không được điều tiết.

Mỗi team của Netflix có thể tự build cơ chế recovery riêng nhưng điều này ảnh hướng tới tính consistency, cần phải có cơ chế chung cho toàn bộ

Do đó Netflix đã build 1 hệ thống WAL gọi là Distributed WAL (Write-Ahead Log)

Kiến trúc này hoạt động dựa trên mô hình Change Data Capture (CDC), bao gồm các thành phần chính sau:

Nguồn dữ liệu (Source DBs): Các cơ sở dữ liệu quan hệ (RDBMS như MySQL, Postgres) nơi ứng dụng ghi dữ liệu chính. Mọi thay đổi (Insert, Update, Delete) đều được ghi vào file WAL cục bộ của DB trước.
Thành phần DBLog (Connector): Một dịch vụ riêng biệt, đóng vai trò là “người lắng nghe”. Nó đọc trực tiếp file WAL nhị phân của cơ sở dữ liệu để phát hiện sự kiện mới.
** Message service (Event Bus - Kafka):** Phân vùng WAL được đẩy lên Kafka. Kafka đóng vai trò là log phân tán, đảm bảo thứ tự và tính kiên định của sự kiện.
Consumer: Các dịch vụ khác (Search Index, Cache, Analytics) subscribe từ Kafka để update status của mình.

Workflow chạy như sau

Ghi local offline (1-2): Ứng dụng ghi dữ liệu vào cơ sở dữ liệu. DB đảm bảo rằng thay đổi được ghi vào file WAL local trước khi xác nhận thành công.
Capture (3-4): DBLog đọc file WAL cục bộ một cách tuần tự. Nó cực kỳ nhanh và không gây tải cho các câu lệnh SQL khác.
Phân tán (5): DBLog chuyển đổi các thay đổi thành event message và đẩy chúng lên Kafka. Kafka giờ đây đóng vai trò là một “Distributed WAL” toàn cục.
Đồng bộ (6): Các dịch vụ hạ nguồn subscribe Kafka và cập nhật trạng thái của mình (ví dụ: cập nhật index tìm kiếm, xóa cache cũ).

Core của hệ thống ở đây là DBLog

Đọc trực tiếp từ Transaction Log: Nó không truy vấn (query) bảng dữ liệu mà đọc trực tiếp các bản ghi nhị phân của DB (như binlog của MySQL hay WAL của Postgres) để extract những thay đổi về dữ liệu
Cơ chế Watermark (Điểm mốc): Đây là sáng kiến giúp giải quyết bài toán “Backfill” (đổ dữ liệu cũ). DBLog chèn các “tín hiệu” (watermark) vào chính luồng WAL để đồng bộ hóa việc đọc dữ liệu lịch sử và dữ liệu thời gian thực mà không gây khóa (lock) cơ sở dữ liệu.
Khả năng chịu lỗi: Nếu tiến trình CDC bị sập, nó có thể tiếp tục đúng vị trí cũ nhờ vào việc lưu trữ các offset trong WAL.

Cơ chế Retry

Trong trường hợp Network error dẫn tới message failed, WAL có thể retry lại theo cơ chế exponantial backoff, hệ thống sẽ tăng dần thời gian chờ giữa các lần retry để có thời gian self-healing

(source: bytebytego)

Netflix không thực hiện retry trực tiếp trên Primary Queue. Vì nếu một tin nhắn bị lỗi và đứng lại ở đầu hàng đợi chính để thử lại, nó sẽ làm tắc nghẽn (Head-of-line blocking) hàng triệu message khác đang đợi phía sau.

Giải pháp: failed message được đẩy sang một Retry Queue riêng. Hàng đợi chính tiếp tục trôi đi, đảm bảo throughput của toàn hệ thống không bị ảnh hưởng bởi một vài message lỗi.

Nếu sau một số lần thử (ví dụ 10 lần) mà vẫn thất bại, message sẽ được chuyển vào DLQ.

Dữ liệu từ Dead Letter Queue (DLQ) được đẩy vào Apache Iceberg để phân tích

Khi một tin nhắn (message) rơi vào DLQ, nó thường mang theo hai loại thông tin:

Payload gốc: Dữ liệu mà hệ thống định xử lý nhưng thất bại.

Metadata về lỗi: Mã lỗi, thời gian xảy ra, ID của worker xử lý, và số lần đã thử lại (retry count).

Apache Iceberg là một định dạng bảng (table format) mã nguồn mở, hiệu suất cao, được thiết kế để quản lý các tập dữ liệu cực lớn (quy mô petabyte) trong data lake. cấu trúc giống SQL, hỗ trợ giao dịch ACID, (schema evolution) và truy vấn dữ liệu hiệu quả bằng các công cụ như Spark, Flink, Trino

Khi failed từ DLQ được đẩy vào Iceberg:

ACID giúp đảm bảo rằng dù có hàng nghìn lỗi đổ về cùng lúc, bảng Iceberg vẫn ghi chép ổn định, không mất mát.

Schema Evolution giúp bạn dễ dàng thêm các cột “Mã lỗi mới” hoặc “Metadata mới” mà không làm hỏng các script phân tích cũ.

Time Travel cho phép kỹ sư quay lại đúng thời điểm hệ thống gặp sự cố để lấy dữ liệu lỗi ra xử lý lại.

Hiểu đơn giản kiểu giaosucan’s blog thì Iceberg là phần mềm quản lý kho, giúp bạn biết chính xác bao tải nào nằm ở đâu, lịch sử nhập xuất thế nào, và đảm bảo không ai lấy nhầm bao tải chưa đóng gói xong.

Netflix biến WAL thành Single Source of Truth: Mọi thay đổi dữ liệu phải được ghi vào Log trước khi thực hiện bất cứ điều gì khác. Nếu Log còn, dữ liệu còn; nếu Log mất, hệ thống vô nghĩa.

Decoupling : Các đội ngũ phát triển ứng dụng không cần quan tâm đến việc dữ liệu sẽ đi đâu (Kafka, Elasticsearch hay S3). Họ chỉ cần ghi vào WAL API, phần còn lại do nền tảng tự động điều phối.

Đăng nhận xét

0 Nhận xét