Kiến trúc Vector Search Low-latency: Sharding, Caching và Hybrid CPU/GPU Strategies

Low-Latency Vector Search Architectures: Sharding, Caching, và Chiến lược Hybrid CPU/GPU

Bởi Anh Hải – Senior Solutions Architect


Giới thiệu

Trong kỷ nguyên AI, Vector Search (tìm kiếm dựa trên vector biểu diễn ngữ nghĩa) đã trở thành xương sống của các ứng dụng như RAG, recommendation system, và search semantic. Tuy nhiên, khi hệ thống xử lý hàng triệu vector mỗi giây, latency (thời gian chờ) có thể leo lên hàng trăm ms – điều không thể chấp nhận được trong ứng dụng real-time.

Hôm nay, mình sẽ đi sâu vào 3 kỹ thuật cốt lõi để giảm latency xuống dưới 50ms:
1. Sharding – Phân tách dữ liệu để tránh bottleneck.
2. Caching – Lưu trữ kết quả truy vấn thường gặp.
3. Hybrid CPU/GPU – Kết hợp sức mạnh xử lý của cả CPU lẫn GPU.

Dưới đây là bản đồ lộ trình:

User Query 
  → Vectorization (Embedding Model) 
  → Sharding Layer (Distribute Requests) 
  → Caching Layer (Check Local Cache) 
  → Hybrid Execution (CPU/GPU Parallelism) 
  → Aggregated Results 
  → Response (≤50ms)

1. Sharding: Phân Tách Dữ Liệu Để Tránh Bottleneck

Tại sao cần Sharding?

Khi dữ liệu vector đạt 50GB+ và truy vấn lên đến 10.000 RPS (requests per second), một đơn vị lưu trữ đơn lẻ sẽ nhanh chóng trở thành điểm hẹp.

Ví dụ kỹ thuật:
Không sharding: 1 node lưu trữ toàn bộ vector → Latency trung bình 220ms.
Sharding 16 node: Mỗi node chỉ xử lý 1/16 dữ liệu → Latency giảm xuống 45ms.

Cách triển khai Sharding

a. Consistent Hashing (Băm nhất quán)
Dùng thuật toán như MurmurHash3 để phân bố đều vector vào các shard.

# Python 3.12 - Consistent Hashing cho Vector Sharding
import mmh3

def assign_shard(vector_id: str, num_shards: int) -> int:
    """Gán vector vào shard dựa trên hash của vector_id"""
    return mmh3.hash(vector_id, signed=False) % num_shards

# Ví dụ: 16 shards
vector_id = "doc_12345"
shard_id = assign_shard(vector_id, 16)  # → Trả về số shard (0-15)

b. Dynamic Re-sharding
Khi hệ thống mở rộng từ 16 → 32 shards, dùng consistent hashing ring để giảm mất dữ liệu:

Shard Map (16 → 32):
[0] → [0, 16]  
[1] → [1, 17]  
...  
[15] → [15, 31]

Công thức tính phân bố tải:

P(\text{balance}) = \frac{N_{\text{shards}}}{N_{\text{total\_shards}}}

Giải thích: Xác suất phân bố đều khi thêm shards mới là tỉ lệ số shards hiện tại so với tổng shards.

Lưu ý quan trọng

⚠️ Cảnh báo: Khi sharding, luôn duy trì index local trên mỗi node (Ví dụ: HNSW trên mỗi shard). Tránh truy vấn cross-shard không kiểm soát – nó sẽ làm latency tăng đột biến.


2. Caching: Giảm Latency Bằng Kết Quả Truy Văn Thường Gặp

Chiến lược Caching Nền Tảng

a. Embedding Cache
Lưu trữ các embedding vectors đã tính trước trong Redis (phiên bản 7.2) với cấu hình:
LRU (Least Recently Used) policy.
TTL (Time-To-Live) 300 giây.

# Python - Lấy embedding từ Redis cache
import redis

r = redis.Redis(host='redis-cache', port=6379, db=0)

def get_embedding(text: str) -> list[float]:
    cache_key = f"emb:{hash(text)}"
    cached = r.get(cache_key)
    if cached:
        return json.loads(cached)  # Trả kết quả từ cache

    # Tính toán embedding mới dùng model (Ví dụ: sentence-transformers)
    embedding = model.encode(text)
    r.setex(cache_key, 300, json.dumps(embedding))  # Lưu vào cache 5 phút
    return embedding

b. Query Result Cache
Lưu kết quả truy vấn gần đây (k-nearest neighbors) vào Memcached (phiên 1.6) với sliding window expiration:

Parameteter Giá trị đề xuất
Max Items 500,000
Expiration 60s
Eviction Policy LFU (Least Frequently Used)

So sánh Redis vs Memcached:

| Tiêu chí          | Redis (7.2)               | Memcached (1.6)         |
|-------------------|---------------------------|-------------------------|
| Độ khó triển khai | Trung bình               | Dễ dàng                |
| Hiệu năng         | ⚡ 300k OPS (SSD)         | ⚡ 1M OPS               |
| Cộng đồng        | Rộng rãi, tính năng đa dạng | Nhỏ hơn, tập trung hiệu năng |
| Learning Curve   | Cao hơn (Cluster, ACL)   | Thấp                   |
Tối ưu Cache Hit Ratio

Công thức tính Cache Hit Ratio:

Hit\_Ratio = \frac{Number\_of\_Cache\_Hits}{Total\_Requests} \times 100

Giải thích: Tỷ lệ phần trăm yêu cầu được phục vụ từ cache. Mục tiêu >70% cho hệ thống vector search.

💡 Mẹo: Dùng stale-while-revalidate – cho phép trả về kết quả cũ trong khi cập nhật cache nền. Giảm latency thêm ~15ms.


3. Hybrid CPU/GPU: Kết Hợp Sức Mạnh Xử Lý Song Song

Vấn đề của GPU đơn lẻ
  • Overhead memory copy: Chuyển dữ liệu từ RAM → VRAM tốn ~20ms.
  • Bottleneck I/O: Khi xử lý >1M vector/giây, GPU dễ bị quá tải.
Chiến lược Hybrid

a. CPU cho Preprocessing
Vector Normalization: Dùng SIMD (Single Instruction, Multiple Data) trên CPU.
Sharding Routing: Xử lý logic phân phối yêu cầu nhanh hơn GPU.

b. GPU cho Tính Toán Tương Đương
Sử dụng FAISS (phiên 1.9.0) với cấu hình IVF512, Flat:

# PyTorch + FAISS trên GPU
import faiss
import torch

d = 768  # Chiều vector
nlist = 512  # Số cluster IVF
quantizer = faiss.IndexFlatL2(d)
index = faiss.IndexIVFFlat(quantizer, d, nlist, faiss.METRIC_INNER_PRODUCT)

# Gán GPU
res = faiss.StandardGPUResources()
index = faiss.index_cpu_to_gpu(res, 0, index)

# Thêm dữ liệu và tìm kiếm
index.add(vectors)  # vectors: torch.Tensor (float32)
distances, indices = index.search(query_vectors, k=10)  # Trả kết quả nhanh

c. Pipeline Song Song

Query → [CPU: Sharding + Cache Check] → [GPU: FAISS Search] → [CPU: Merge Results] → Response

Công thức tính latency tối ưu:

Latency_{total} = Latency_{CPU} + Latency_{GPU} + Overhead_{transfer}

Giải thích: Tổng latency là tổng thời gian xử lý CPU, GPU và overhead chuyển dữ liệu. Mục tiêu <50ms.

Bảng so sánh hiệu năng
Công nghệ Latency (ms) Throughput (RPS) Memory Usage (GB/1M vector)
FAISS (CPU) 110 2,000 7.5
FAISS (GPU RTX4090) 45 15,000 15
Hybrid (CPU+GPU) 35 20,000 12

🐛 Lỗi thường gặp: Quá tải GPU khi dùng batch size quá lớn. Giới hạn batch size = 512 để tránh OOM (Out Of Memory).


4. Tổng Kết & Kiến Nhận

3 điểm cốt lõi để đạt latency <50ms:
1. Sharding phân tán tải đều, giảm latency từ 220ms → 45ms.
2. Caching tăng Cache Hit Ratio >70%, cắt giảm ~50% thời gian tính toán.
3. Hybrid CPU/GPU tối ưu hóa pipeline, giảm latency thêm ~10ms.

Câu hỏi thảo luận:
– Anh em đã từng gặp tình huống latency bùng lên đột ngột do cache miss hay GPU overload chưa? Cách xử lý là gì?

Gợi ý hành động:
Nếu đang xây dựng hệ thống RAG hay search semantic và lo lắng về scaling, hãy thử noidungso.io.vn – bộ công cụ hỗ trợ tối ưu hóa vector search mà không cần viết code phức tạp.

Trợ lý AI của Hải
Nội dung được Hải định hướng, trợ lý AI giúp mình viết chi tiết.
Chia sẻ tới bạn bè và gia đình