Solutions


🔁 1. Resharding (Tái phân phối dữ liệu khi thay đổi số lượng shard)

🎯 Vấn đề:

  • Khi thêm/bớt shard (ví dụ: mở rộng từ 4 lên 6 shard), hashing hoặc phân vùng cũ không còn chính xác, dẫn đến cần di chuyển nhiều dữ liệu giữa các node.

  • Ảnh hưởng performance, downtime, consistency.

✅ Cách giải quyết:

➤ Hashing with consistent hashing:

  • Thay vì hash(key) % number_of_shards, dùng Consistent Hashing để giới hạn lượng dữ liệu cần di chuyển khi thêm shard.

  • Lợi ích: Giảm dữ liệu phải migrate ~ 1/N.

➤ Use middleware hỗ trợ Resharding tự động:

  • Ví dụ: sử dụng Vitess, CockroachDB, Citus, hoặc dùng Sharding Manager Layer tự viết để track vị trí key.

  • Có thể hỗ trợ online resharding với background replication & sync.

➤ Pre-split ranges (range-based sharding):

  • Với Range sharding, nên thiết kế trước các khoảng giá trị để dễ scale. Sau đó gộp/tách các range theo nhu cầu.


🔥 2. Celebrity Problem / Hotspot Key Problem

🎯 Vấn đề:

  • Một số key quá phổ biến (VD: user_id = 0 là admin, hoặc product_id = 100 là flash sale) → mọi request đổ dồn vào 1 shard → bottleneck, overload.

✅ Cách giải quyết:

➤ Data replication cho hotspot:

  • Replicate dữ liệu "hot" ra nhiều shard (read replica).

  • Load balancing qua cache layer (Redis cluster) hoặc Read-Only replicas.

➤ Key diversification (key suffixing hoặc salting):

  • Thay vì lưu vào key hotKey, lưu vào hotKey_1, hotKey_2,... và client/app layer random hoặc chia hash để truy cập.

  • Sau đó aggregate lại nếu cần (chấp nhận eventual consistency).

➤ Đẩy hot data vào cache layer (Redis, Memcached):

  • Đặc biệt hiệu quả nếu data đọc nhiều, ghi ít.

  • Đặt TTL ngắn hoặc sử dụng cache-aside pattern.

➤ Thay đổi chiến lược partitioning:

  • Nếu Hotspot là do Range Sharding thì cân nhắc chuyển sang Hash-based sharding.


🔗 3. Join Across Shards (Cross-shard join)

🎯 Vấn đề:

  • Khi cần join dữ liệu giữa 2 table nhưng chúng ở 2 shard khác nhau → rất tốn tài nguyên hoặc không thực hiện được native trong SQL.

✅ Cách giải quyết:

➤ Denormalization (Tái thiết kế dữ liệu):

  • Tối ưu nhất: tránh join bằng cách copy dữ liệu cần thiết (tức là lưu trùng), nhất là khi dữ liệu ít thay đổi.

➤ Co-locating related data:

  • Đặt các bảng liên quan vào cùng 1 shard theo khóa chung (composite sharding key).

    • Ví dụ: useruser_orders nên shard theo user_id → join được nội bộ trong shard.

➤ Application-level join:

  • Tách query và thực hiện join ở tầng service:

    • Query shard A → lấy ID list → query shard B → xử lý join logic.

    • Có thể kết hợp với async hoặc parallel query để giảm độ trễ.

➤ Use a distributed SQL engine:

  • Ví dụ: Vitess, TiDB, Citus, Presto/Trino: hỗ trợ join phân tán hiệu quả.


📌 Tổng kết bảng:

Vấn đề
Giải pháp chính

Resharding

Consistent Hashing, Middleware (Vitess, Citus), Pre-split ranges

Hotspot Key

Replication, Cache, Key salting, Hashing, Load balance

Cross-shard Join

Denormalization, Co-location, App-level join, Distributed SQL engine


Nếu bạn đang dùng Java + Spring + MySQL/PostgreSQL, bạn có thể cân nhắc:

  • Redis Cluster cho cache + load balancing hotspot.

  • Apache ShardingSphere hoặc Vitess nếu cần abstract sharding logic.

  • Hibernate custom sharding logic nếu muốn kiểm soát cao.


Last updated