MongoDB gục lúc 3h sáng — AI pipeline vô tội
Khi RAG pipeline trả rác, ai cũng đổ cho prompt. Nhưng thủ phạm thật sự có khi nằm ở tầng database mà chẳng ai thèm ngó.
Bụi WireTuần trước mình ngồi debug cùng một team 4 người ở Đà Nẵng. RAG pipeline của họ chạy demo ngon lành, lên staging thì cứ 10 query có 3 cái trả kết quả cũ rích — kiểu bạn hỏi "chính sách hoàn tiền mới nhất" mà nó trả về bản tháng trước. Hai ngày ròng, cả team lật tung prompt, thay embedding model, chỉnh chunk size. Cuối cùng thủ phạm là ai? MongoDB secondary node bị lag replication gần 45 giây mà không ai hay.
Nói thẳng ra: AI pipeline của bạn có thể hoàn hảo — nhưng nếu database ho, cả hệ thống sập.
"Xe buýt" dữ liệu đến trễ một chặng
Hình dung MongoDB replica set như hệ thống xe buýt nội thành. Primary node là bến trung tâm — tất cả dữ liệu mới đều xuất phát từ đây. Các secondary node là những tuyến nhánh, nhận dữ liệu rồi phục vụ hành khách (tức read queries) ở từng trạm.
Khi replication lag tăng, chuyện xảy ra y hệt xe buýt trễ giờ: hành khách lên xe ở trạm phụ, nhưng nhận được "hàng" cũ vì chuyến mới chưa kịp đến. Với app thông thường, trễ vài giây có khi không ai để ý. Nhưng với RAG pipeline — nơi vector search đang đọc từ secondary — 45 giây lag nghĩa là user nhận câu trả lời dựa trên document chưa được index.
Kiểm tra bằng cách nào? Chạy rs.status() trong MongoDB shell, tìm dòng optimeDate của từng member rồi so sánh. Nếu khoảng cách giữa PRIMARY và SECONDARY hơn vài giây, bạn có vấn đề.
Ba chốt kiểm tra builder AI hay quên
Mình thấy đa số team Việt Nam xây AI system đều focus vào model layer mà bỏ quên database layer. Đây là ba điểm cụ thể:
1. Replication health
Chạy rs.status() và xác nhận mọi member đều ở trạng thái PRIMARY hoặc SECONDARY. Nếu thấy member nào RECOVERING hoặc DOWN, đó là đèn đỏ. Trên Atlas UI, vào trang Clusters → click tên cluster → tab Overview cũng hiển thị trạng thái tương tự.
2. Oplog window — bộ nhớ đệm của replica set
Oplog là nơi MongoDB lưu lịch sử thay đổi để secondary bắt kịp. Hiểu nôm na: nó như kênh bộ đàm trên tuyến xe buýt — nếu kênh quá ngắn, tài xế nhánh bỏ lỡ thông báo thì phải quay về bến chính đồng bộ lại từ đầu. Kiểm tra bằng rs.printReplicationInfo() — nếu oplog window dưới 24 giờ, bạn đang sống nguy hiểm.
3. Write concern — dữ liệu ghi xong thật chưa?
Khi RAG pipeline ingest document mới, write concern quyết định "ghi vào mấy node mới tính là xong". Mặc định w:1 nghĩa là ghi vào primary là xong — secondary chưa chắc có. Với hệ thống AI cần consistency, nên set w: "majority" để dữ liệu đã replicate sang đa số node trước khi confirm.
Kịch bản thật: Atlas free tier, RAG nội bộ, và cú vấp lúc scale
Giả sử team bạn 5 người, đang dựng chatbot nội bộ dùng MongoDB Atlas free tier (M0) làm document store cho RAG. Mọi thứ chạy mượt với 500 documents. Nhưng khi dataset lên 10,000 documents:
- Query bắt đầu chậm vì thiếu index phù hợp
- M0 không cho tạo custom index trên nhiều field
- Monitoring bị giới hạn, slow query trốn kín
Hướng xử lý: Upgrade lên M10 (shared cluster có monitoring đầy đủ) hoặc — nếu budget eo hẹp — self-host MongoDB Community trên VPS. Như mình đã chia sẻ trong bài về GLM 5.1 local, việc self-host ban đầu tốn công setup nhưng cho bạn toàn quyền kiểm soát. Cài thêm MongoDB Compass (free) để visualize performance metrics thay vì nhìn JSON output từ shell.
Thử ngay chiều nay — health check trong 20 phút
Bước 1: Kết nối vào MongoDB shell
mongosh "mongodb+srv://your-cluster.mongodb.net" --username admin
Bước 2: Kiểm tra replica set status
rs.status().members.forEach(m => {
print(`${m.name} — state: ${m.stateStr}, lag: ${m.optimeDate}`)
})
Bước 3: Đo oplog window
rs.printReplicationInfo()
Bước 4: Tìm slow queries đang âm thầm giết performance
db.currentOp({"secs_running": {$gt: 5}})
Bước 5: Set alert cơ bản trên Atlas — vào Alerts → tạo rule cho replication lag > 10 giây và connections > 80% limit. Hai alert này một mình đã chặn được phần lớn sự cố "3 giờ sáng".
Bẫy kinh điển: "Managed service lo hết rồi"
Không ít team nghĩ dùng Atlas thì không cần monitor. Plot twist: Atlas cho bạn tool monitor, nhưng không tự sửa khi replication lag tăng hay index bị miss. Nó giống xe có camera lùi — camera chỉ hiển thị chướng ngại vật, đạp thắng vẫn là việc của bạn.
Một bẫy khác đau không kém: chạy db.collection.find() không có .explain() rồi kết luận "query nhanh mà". Trên dataset nhỏ thì cái gì cũng nhanh. Thử db.collection.find({...}).explain("executionStats") trên data production-size, bạn sẽ thấy MongoDB thật sự phải scan bao nhiêu document — con số đó mới là sự thật.
Khi nào nên rẽ hướng khác?
Nếu use case chủ yếu là vector search cho RAG, MongoDB Atlas Vector Search tiện vì tích hợp sẵn. Nhưng nếu bạn cần chạy offline hoặc phần cứng hạn chế — ví dụ kết hợp với model nhẹ kiểu Bonsai 1-bit chạy local trên laptop cũ — thì SQLite + một vector extension như sqlite-vss có thể đủ dùng mà nhẹ hơn đáng kể.
Dịch sang tiếng người: không phải "database nào xịn nhất" mà là chọn xong thì phải biết cách đo sức khoẻ nó. Replica set đẹp mấy mà không ai ngó oplog thì cũng như mua xe xịn rồi không bao giờ thay dầu — chạy được một đoạn rồi chết máy giữa đường.
---
Bụi Wire — nghiện đọc release notes lúc 2 giờ sáng