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

Ticker

20/recent/ticker-posts

Kiến trúc FAANG 5 - Discord lưu nghìn tỉ message như thế nào?

Tiếp tục bài trước , câu chuyện về cách Discord lưu trữ hàng tỷ message thế nào, khi họ chuyển đổi mô hình NoSQL truyền thống sang cơ sở dữ liệu Cassandra

Nhưng số lượng user của Discord phát triển quá nhanh, Đến năm 2017, Discord có khoảng 12 Cassandra node, lưu hàng tỷ message. Sang năm 2022, con số đó lên tới 177 node, lưu nghìn tỷ message, và Cassandra gặp vấn đề về performance

Câu chuyện cụ thể là như thế nào, hãy xem cấu trúc của một discord message cơ bản

CREATE TABLE messages (

channel_id bigint, message_id bigint, author_id bigint, content text, PRIMARY KEY (channel_id, message_id)
) WITH CLUSTERING ORDER BY (message_id DESC);

Message thì có message id (được định danh theo snowflex, đã mô tả ở bài trước), channel ID, là nơi chứa message, các thông tin này được lưu trong 3 node cassandra replicas

Nhược điểm của Cassandra là việc đọc dữ liệu performance lại kém hơn ghi. Vì các ghi dữ liệu của Cassandra không giống như mấy kiểu DB thông thường, mỗi khi có thay đổi dữ liệu nó sẽ ghi vào commit logs và memtable (một dạng cache) trước , chứ không thực sự ghi vào DB. Đến thời điểm nào đó thì mới thực sự write vào DB. Cái này cũng tương tự như chơi tá lả ăn tiền, mỗi trận đều ghi điểm, sau khi tàn cuộc mới thanh toán. Nhờ đó mà việc ghi khá nhanh

Tuy nhiên khi đọc, Cassandra phải query lại những memtable trên, lúc này là cả một vấn đề vì những lần thay đổi về data nằm cả trên đây, nên tốc độ đọc thật sự là thảm họa, bị latency liên tục, do số lượng concurrent read tăng mạnh, lượng data thì tới hàng nghìn tỉ, nên Cassandra gặp phải vấn đề Garbage Collector, vấn đề GC như thế nào đã được mô tả ở bài 1, và mỗi lần GC xảy ra, operator phải restart lại Cassandra bằng cơm, ảnh hưởng đến stability của hệ thống

Do đó cần phải chuyển đổi sang loại DB khác có khả năng scale và performance tốt hơn, kỹ sư của Discord đã chuyển sang ScyllaDB, một dạng db tương thích với Cassandra và DynamoDB


ScyllaDB cũng sử dụng kiến trúc vòng RING như Cassandra, một cluster gồm nhiều node, mỗi node bao gồm các shards để lưu trữ data, các node này chính là các server vật lý hoặc virtual, và data sẽ được replicas đều vào các node

Mấy khái niệm về data sharding nếu đọc Google có thể hơi mù mờ , có thể hiểu nhanh là nếu bạn là chủ 1 công ty có 1 triệu nhân viên đánh mã số từ 1 đến 1T, nếu nhét hết vào 1 bảng excel thì dài dằng dặc, truy vấn tìm kiếm mất nhiều thời gian. Giờ sẽ chia ra thành nhiều sheet excel, sheet 1 là 100K em đầu , sheet 2 thì 100K em tiếp theo. Muốn truy vấn id nào thì mở sheet tương ứng tìm cho nhanh


Việc truy vấn dữ liệu vẫn dùng CQL language, API như Cassandra

Nhìn đi nhìn lại thấy ô Scylla này không khác gì Cassandra, thế sao Discord phải nghiên cứu đổi làm gì? Điểm keypoint ở đây là Scylla được phát triển bẳng C++, nó giải quyết được Garbage Collector, Java Overhead, vấn đề mà Cassandra (viết bằng Java) gặp phải khi lưu trữ đến nghìn tỉ message. Ngoài ra các thông số khác như throughput, performance cho thấy ScyllaDB tốt hơn

Sau nhiều thử nghiệm thì Discord quyết định là migrate hết database sang ScyllaDB.

Big Migration

Tuy nhiên để migrate existing Cassandra với nghìn tỉ message sang ScyllaDB cũng không phải là chuyện dễ dàng

Vẫn còn một issue đang khó giải quyết gọi là “hot partition”

Như ta đã biết cách data được lưu theo partition như ở dưới, data sẽ được phân bố đều vào các partition


Nhưng đó là trường hợp lý tưởng, có những trường hợp một lượng message khổng lồ được ghi vào data trong thời gian ngắn ( Kiểu thanh niên nào xài bot spam message đồng loạt vào room), lúc này ScyllaDB ko thể xử lý phân bố dữ liệu được, dẫn tới 1 lượng lớn data ghi vào một partition tạo ra “hot parition”

Cái này thì các kĩ sư Discord vẫn phải mò

Migrate trillions message mà ko Downtime

Tạo Cluster ScyllaDB

Đầu tiên thì phải tạo 1 cluster ScyllaDB dùng super-disk storage topology, giải thích thì khá khó hiểu, hiểu nhanh kiểu gsc như này

Ai cũng biết đó là thay vì chơi HDD thì xài SSD để tăng tốc độ đọc ghi (Chơi game suốt biết cái này rồi) Hệ thống discord xài GCP nên họ dùng local SSD, loại disk này là physical attach thẳng vào server nên performance rất ngon. Nhưng là loại vật lý nên nhỡ disk lỗi cái là bay sạch data, và mỗi lần attach/detach disk sẽ gây downtime trên server

Ngoài ra còn loại disk truyền thống là persistent disk, loại disk này có thể tăng giảm size thoải mái mà ko downtime, snapshot ngon lành, attach/detach on the fly , nhưng nó lại ko attach trực tiếp vào server được nên performance chậm

Hiểu đơn giản thì local SSD của discord nó như là cái ổ đĩa win trên máy tính, còn HDD nó như cái ổ cắm USB. Muốn thay ổ thì phải tắt máy, nó có trục trặc thì chỉ có nc cài lại win. Còn HDD thì plug and play hot swap thoải mái

Do đó supper-disk storage topology là tạo ra một loại disk mới kết hợp sức mạnh của 2 loại trên

Migrate Data

Do Scylla và Cassandra tương thích nên việc migrate khá straightforward, họ dùng ScyllaDB’s Spark migrator được thực hiện dual-writing từ Cassandra to Scylla

Cuối cùng thì việc migration cũng hoàn thành xong , từ 177 cassandra node sang 72 node ScyllaDB, mỗi node 9TB so với 4TB của Cassandra

Kết quả cũng rất khả quan

Fetching historical messages had a p99 of between 40-125ms on Cassandra, with ScyllaDB having a nice and chill 15ms p99 latency, and message insert performance going from 5-70ms p99 on Cassandra, to a steady 5ms p99 on ScyllaDB

Đăng nhận xét

0 Nhận xét