MemSQL Architecture - The Fast (MVCC, InMem, LockFree, CodeGen) And Familiar (SQL)
Bài tóm tắt MemSQL 2012 2. Tăng trưởng Độ khó: Khó
MemSQL (SingleStore) · 2012 · 2. Tăng trưởng · Độ khó: Khó — bài gốc
Bài phỏng vấn hai đồng sáng lập MemSQL (sau này đổi tên thành SingleStore) do Todd Hoff (HighScalability) viết lại, tức là theo MemSQL qua lời kể của HighScalability. Lúc đó là bản phát hành đầu: chưa có sharding (dự kiến cuối 9/2012), SQL rất hạn chế. Benchmark của MemSQL bị cộng đồng MySQL phản bác (bài "MySQL is bazillion times faster than MemSQL" của Domas Mituzas).
Bối cảnh
- Hai nhà sáng lập từng ở Facebook (nền tảng, hạ tầng; một người từng làm lõi SQL Server). Theo họ, Facebook scale được nhờ hai thứ: Memcached (KV trong RAM) và sinh code (HipHop dịch PHP sang C++). Ghép hai ý vào database: DB trong RAM nhưng giao diện là SQL thay vì KV.
- Đối tác của Facebook đụng scale rất nhanh (game thêm 2–3 triệu user trong vài tuần). Theo họ, đọc nhanh từ RAM đã được Memcached giải; ghi nhanh thì chưa.
- Số liệu họ công bố (2012): 200K TPS trên một EC2 lớn, 1,2 triệu TPS trên máy 64 core; cụm lớn nhất 500 node; 20 tỉ bản ghi một bảng trên một máy.
Thiết kế
- Giả định dữ liệu vừa RAM. Không có buffer pool; không query đọc nào phải chờ đĩa.
- Lock-free mọi nơi: linked list, queue, stack, skip list, hash table. Ghi nhanh bằng cách bỏ tranh chấp.
- Skip list thay B-tree cho range query: dễ làm lock-free, scale tốt khi nhiều luồng. Đánh đổi: quét tuần tự dài chậm hơn chút; skip list lock-free chỉ một chiều, cần cả tăng lẫn giảm thì phải hai index.
- MVCC: mỗi lần sửa tạo phiên bản mới (danh sách liên kết lock-free); chỉ khoá khi hai giao dịch cùng ghi một dòng (dễ lập trình hơn là bắt giao dịch thứ hai thất bại); hàng dòng đã sửa được đưa cho garbage collector để khỏi quét cả bảng.
- Sinh code: SQL → C++ → GCC → shared object, nạp vào DB. Parser hai pha: lớp nhẹ bỏ hằng số để ra "hình dạng" query, tra trong hash table lock-free; trúng thì chạy code đã biên dịch, trượt thì parse đầy đủ và biên dịch (0,5–10 giây mỗi query lúc đầu). Plan biên dịch giữ qua lần khởi động lại.
- Độ bền: giao dịch commit vào buffer trong RAM rồi ghi đĩa bất đồng bộ; một thread flush log vài mili giây một lần với group commit. Buffer bằng 0 thì đồng bộ hoàn toàn. Log đạt 2 GB thì nén thành snapshot; khôi phục = đọc snapshot (nhiều luồng) + replay phần log còn lại. Chỉ ghi tuần tự.
- Replication: theo dòng, master/nhiều slave, đồng bộ hoặc bất đồng bộ (vài ms trễ). Thêm slave online bằng cách gửi snapshot rồi replay log, khớp với cơ chế độ bền. Không làm master-master vì mất nhất quán.
- Phân tán (sắp ra): aggregator chia query và gom kết quả, leaf shared-nothing giữ dữ liệu; hash hoặc range partitioning, consistent hashing; MVCC chỉ trong một leaf, không có giao dịch xuyên shard cho tới khi làm 2PC. Metadata tập trung (MemSQL, MySQL hoặc ZooKeeper).
- Giao thức MySQL thay vì tự viết client: dùng được mọi driver và công cụ sẵn có.
- Bộ nhớ:
maximum_table_memoryvượt thì chặn ghi, đọc vẫn chạy.
Vì sao
- Mỗi lựa chọn đi ra từ hai giả định: dữ liệu nằm trong RAM và cần thực thi SQL thật nhanh. Bỏ đĩa khỏi đường đọc thì nút thắt chuyển sang tranh chấp CPU và chi phí diễn giải query (Chọn database theo workload).
- Đĩa chỉ còn dùng cho ghi tuần tự theo nhóm, nên group commit là cách lấy throughput ghi (Batching và khấu hao round-trip).
Bài học cho SWE
- Một DB "nhanh nhất" luôn có giả định đi kèm (vừa RAM, SQL hạn chế, chỉ READ COMMITTED, giao dịch một câu lệnh, ghi đĩa bất đồng bộ mặc định). Đọc giả định trước khi đọc benchmark.
- Snapshot + log là một cơ chế làm ba việc: khôi phục, sao lưu, dựng replica mới (Failover, replica và dự phòng dữ liệu).
- Dùng giao thức có sẵn (MySQL) là cách rẻ nhất để người ta thử sản phẩm.
- Shared-nothing không 2PC scale gần tuyến tính, nhưng đẩy tính nhất quán xuyên shard về phía ứng dụng.
Liên quan
#In-memory database#MVCC#Lock-free#Skip list#Code generation#Group commit#Snapshot + log#Aggregator/leaf#Shared nothing#MySQL protocol
Được nhắc tới trong
Chủ đề (3)
Công ty (1)