01 Vấn đề & ý tưởng
Trong web truyền thống, dễ scale web/app server, nhưng CSDL là nút cổ chai cuối cùng: tải cao tới mức tạo "hình tam giác" thắt lại ở DB. Vá bằng cache hay scale DB đều khó & đắt.
Giải bài toán mở rộng cực hạn ở tầng kiến trúc thường tốt hơn là cố scale DB hay nhồi cache vào một kiến trúc vốn không scale được.
Richards & FordTên gọi đến từ tuple space — nhiều bộ xử lý song song giao tiếp qua bộ nhớ dùng chung. Ý tưởng cốt lõi: bỏ DB khỏi đường giao dịch đồng bộ, giữ dữ liệu in-memory replicated trên mọi processing unit. Không còn nút cổ chai DB → mở rộng "gần như vô hạn".
Ba điểm mạnh dẫn dắt: Elasticity, Scalability, Performance — cả ba đều 5★. Đổi lại là sự phức tạp (xử lý nhất quán cuối cùng & chống mất dữ liệu).
02 Bốn nhóm thành phần
flowchart TB REQ["Request (tải biến động)"]:::ext --> MG["Messaging Grid
(định tuyến + session)"]:::mw MG --> PU1["Processing Unit + cache"]:::pu MG --> PU2["Processing Unit + cache"]:::pu MG --> PU3["Processing Unit + cache"]:::pu PU1 <-->|"Data Grid replicate <100ms"| PU2 PU2 <-->|"replicate"| PU3 DM["Deployment Manager
(bật/tắt PU theo tải)"]:::mw -.giám sát.-> PU1 DM -.-> PU2 DM -.-> PU3 classDef ext fill:#f3e6c8,stroke:#9a6712,color:#1c1a14; classDef mw fill:#14233b,stroke:#14233b,color:#f3ede0; classDef pu fill:#e7ddf2,stroke:#6a4ca8,color:#1c1a14;
Processing Unit
Chứa logic ứng dụng + in-memory data grid (Hazelcast, Apache Ignite, Coherence). Đọc/ghi cache, không đụng DB trực tiếp.
Messaging Grid
Chọn PU còn rảnh để chuyển request (round-robin → next-available). Thường là load balancer (HAProxy, Nginx).
Data Grid
Sao chép dữ liệu giữa các PU cùng tên cache để mọi PU giống hệt nhau. Đây là trái tim của SBA.
Deployment Manager
Theo dõi tải & thời gian phản hồi để khởi chạy/tắt PU — cốt lõi của tính đàn hồi (elasticity).
Processing Grid (tùy chọn): điều phối request khi một giao dịch cần phối hợp nhiều loại PU khác nhau.
03 Đồng bộ về DB — bất đồng bộ
Vì PU không đọc/ghi DB trực tiếp, dữ liệu chảy về kho thật qua ba thành phần — luôn bất đồng bộ, cho nhất quán cuối cùng giữa cache & DB:
Data Pump
PU cập nhật cache → trở thành "chủ" thay đổi → đẩy update qua messaging (hàng đợi bền vững, FIFO) tới data writer. Decoupling: writer chết thì PU vẫn chạy.
Data Writer
Nhận từ data pump & ghi thật vào DB. Thường theo domain (Customer) hoặc riêng từng loại PU (Wallet).
Data Reader
Chỉ đọc DB khi cần khôi phục: mọi PU của một cache sập, redeploy toàn bộ, hoặc lấy dữ liệu lưu trữ. PU đầu tiên giành lock thành "chủ cache tạm" rồi nạp lại qua reverse data pump.
HazelcastInstance hz = Hazelcast.newHazelcastInstance();
Map<String, CustomerProfile> cache = hz.getReplicatedMap("CustomerProfile");
// Mọi PU có cùng đoạn này → đổi ở một PU, tự replicate sang tất cả PU khác
04 Xung đột dữ liệu & loại cache
Data collision: ở chế độ active/active, hai PU cùng sửa một mẩu dữ liệu trước khi replicate kịp → ghi đè sai (A đặt kho 490, B đặt 495, rồi B bị replicate đè về 490). Tần suất phụ thuộc: số PU (N), tỉ lệ cập nhật (UR), kích thước cache (S) và độ trễ sao chép (RL).
RL ảnh hưởng cực mạnh: với 72.000 update/giờ, RL = 100ms → ~14 va chạm/giờ (0,02%); giảm RL còn 1ms → chỉ ~0,1 va chạm/giờ. Đó là lý do phải đo RL thực tế ở production.
Replicated vs Distributed caching
| Tiêu chí | Replicated (mặc định) | Distributed |
|---|---|---|
| Vị trí dữ liệu | In-memory trong từng PU | Server cache trung tâm riêng |
| Hiệu năng | Cực nhanh (cục bộ) | Thấp hơn (truy cập từ xa) |
| Chịu lỗi | Cao — không điểm sập đơn | Yếu — sập cache server là liệt |
| Nhất quán | Thấp hơn (có độ trễ replicate) | Cao — dữ liệu một chỗ |
| Dung lượng | Giới hạn RAM máy ảo (~<100MB) | Lớn (>500MB) |
Cache nhỏ & ít cập nhật → chọn theo nhất quán (distributed) vs hiệu năng/chịu lỗi (replicated). Dữ liệu cần chính xác cao (tồn kho) → distributed; dữ liệu ít đổi (mã/tên tham chiếu) → replicated. Có thể lai bằng near-cache.
05 Rating & hệ RAG
SBA tối đa hoá đàn hồi, mở rộng, hiệu năng (cả ba 5★) — đổi lại cực phức tạp & gần như không test nổi ở quy mô thật.
Hợp với: bán vé hoà nhạc, đấu giá trực tuyến — tải vọt từ vài trăm lên hàng chục nghìn người trong vài phút, không đoán trước được. Tránh khi: ngân sách hạn chế (phí license cache + tài nguyên cloud) hoặc không kham nổi việc test đàn hồi quy mô lớn.
Khi nào RAG cần SBA?
RAG Một tài liệu/sự kiện "viral" khiến cả công ty hỏi cùng lúc → vector DB thành nút cổ chai. Giữ chunk & embedding "nóng" trong data grid replicated, Deployment Manager bung thêm query node theo tải, data pump async-ghi ingest mới về vector DB.
flowchart TB
Q["Truy vấn dồn dập"]:::ext --> MG["Messaging Grid"]:::mw
MG --> R1["RAG node + cache embedding nóng"]:::pu
MG --> R2["RAG node + cache embedding nóng"]:::pu
R1 <-->|replicate| R2
R1 -->|"data pump (async)"| W["Data Writer"]:::mw --> VDB[("Vector DB (kho thật)")]:::db
classDef ext fill:#f3e6c8,stroke:#9a6712,color:#1c1a14;
classDef mw fill:#14233b,stroke:#14233b,color:#f3ede0;
classDef pu fill:#e7ddf2,stroke:#6a4ca8,color:#1c1a14;
classDef db fill:#e2edf3,stroke:#2f6d93,color:#1c1a14;
RAG Nhưng nhớ "ít tệ nhất": với RAG nội bộ tải vừa phải, SBA là dùng dao mổ trâu — Service-Based (topic 08) thường đủ & rẻ hơn nhiều. Chỉ rút SBA ra khi tải thực sự cực hạn & biến động.
06 Ghi nhớ nhanh
Gỡ DB khỏi đường giao dịch — dữ liệu in-memory replicated giữa các PU; DB chỉ là kho ghi bất đồng bộ. Hết nút cổ chai.
5★ cho elasticity · scalability · performance — ba động lực chính; đổi lại 1★ simplicity & testability.
4 thành phần — Processing Unit (+ data grid) · Messaging Grid · Data Grid · Deployment Manager (đàn hồi).
Data pump → writer → reader — đồng bộ về DB bất đồng bộ; nhất quán cuối cùng; cẩn thận mất dữ liệu khi sập.
Chỉ rút ra khi tải cực hạn & biến động — bán vé, đấu giá; phức tạp & đắt, đừng dùng cho tải vừa phải.