Elasticsearch Bài học 47: Sizing Elasticsearch - Mẹo tính toán dung lượng RAM (Heap size), CPU và số lượng Shard hợp lý
Trong quá trình làm việc với các hệ thống backend chịu tải cao, dù là thiết kế luồng search sản phẩm cho Hasaki hay hệ thống phân tích log thẻ từ cho tuyến Metro AFC, chắc chắn sẽ có lúc bạn phải tự tay lên cấu hình (Sizing) cho cụm Elasticsearch trước khi xin sếp ngân sách mua server.
Nếu cấp phát thừa, công ty lãng phí hàng ngàn đô la mỗi tháng. Nếu cấp phát thiếu, hệ thống sẽ gặp lỗi OOM (Out Of Memory), rớt node liên tục, và API Backend của bạn sẽ bị timeout.
Sizing Elasticsearch vừa là khoa học vừa là nghệ thuật. Dưới đây là những nguyên tắc "xương máu" để bạn tính toán RAM, CPU và Shard một cách chuẩn xác nhất.
1. Quy tắc vàng về RAM: 50% Rule và Lời nguyền 32GB
Trái tim của Elasticsearch là Java Virtual Machine (JVM). Khi bạn thuê một con server (ví dụ 64GB RAM), câu hỏi đầu tiên là: Phải chia bao nhiêu RAM cho Elasticsearch?
Quy tắc số 1: Luôn cấp phát đúng 50% tổng RAM vật lý cho JVM Heap. Nếu server có 64GB RAM, bạn cấu hình tham số ES_JAVA_OPTS="-Xms32g -Xmx32g".
- Tại sao không cấp 100%? Vì Inverted Index cực kỳ phụ thuộc vào bộ đệm của Hệ điều hành (OS Filesystem Cache). 50% RAM còn lại mà bạn không cấu hình sẽ được OS dùng để load các file Index trực tiếp lên RAM, giúp tốc độ tìm kiếm nhanh như chớp. Nếu bạn ép JVM ăn hết RAM, HĐH sẽ không còn chỗ để cache file, và mọi query sẽ phải chạm xuống ổ cứng vật lý (rất chậm).
Quy tắc số 2: Lời nguyền 32GB (Zero-based Compressed Oops). Tuyệt đối KHÔNG BAO GIỜ cấp phát Heap Size vượt quá ngưỡng 31.5GB (hoặc 32GB tùy môi trường).
-
Lý do: Trong Java, khi bộ nhớ dưới 32GB, nó sử dụng một kỹ thuật nén con trỏ (Compressed Oops) giúp con trỏ chỉ tốn 32-bit thay vì 64-bit.
-
Nếu bạn cấu hình JVM Heap là
40GB, Java sẽ tắt tính năng nén này. Kết quả là các object bị phình to, và 40GB RAM lúc này thậm chí còn lưu được ít dữ liệu hơn so với 30GB RAM có nén con trỏ. -
Hệ quả thiết kế: Nếu bạn mua một con server siêu to khổng lồ có 128GB RAM, bạn vẫn chỉ được cấp cho Elasticsearch tối đa 31GB. (Phần còn lại ~90GB sẽ làm Filesystem Cache). Nếu muốn tận dụng RAM để tính toán Aggregations phức tạp, tốt hơn là mua 2 con server 64GB thay vì 1 con 128GB.
2. Tính toán CPU: Search vs. Log
Sức mạnh CPU quyết định số lượng luồng (Thread Pools) mà Elasticsearch có thể xử lý đồng thời. Việc chọn CPU phụ thuộc hoàn toàn vào đặc thù nghiệp vụ:
Kịch bản 1: Hệ thống E-commerce (Như Hasaki - Read-Heavy)
-
Đặc điểm: Tần suất Ghi (Indexing) rất thấp, nhưng tần suất Đọc (Search) và Aggregations cực kỳ cao.
-
Hành vi CPU: Quá trình Scatter-Gather (Bài 10) và chấm điểm BM25 (Bài 28) đòi hỏi tính toán toán học liên tục.
-
Cấu hình: Ưu tiên số lượng nhân CPU (Core) nhiều. Một Node lý tưởng cho Search nên có từ 16 Core đến 32 Core. RAM có thể ở mức 32GB - 64GB.
Kịch bản 2: Hệ thống Logging/Time-series (Như AFC Metro - Write-Heavy)
-
Đặc điểm: Đổ hàng chục ngàn log mỗi giây (Indexing cao), thi thoảng mới có người vào xem Dashboard (Read thấp).
-
Hành vi CPU: CPU chủ yếu làm nhiệm vụ parse JSON, ghi Translog và nén Segment.
-
Cấu hình: Không cần quá nhiều Core (chỉ cần 8 Core đến 16 Core là đủ), nhưng đòi hỏi tốc độ xung nhịp cao và ổ cứng SSD cực nhanh (NVMe) để giải phóng hàng đợi I/O.
3. Quản trị Shard: Kẻ thù giấu mặt gây cạn kiệt RAM
Đây là lỗi phổ biến nhất của các System Admin. Họ nghĩ rằng "Có ILM rồi, cứ để hệ thống tự tạo Index mỗi ngày, mỗi Index cho 5 Shards". Sau 1 năm, cụm Elasticsearch có tới 10.000 Shards.
Hãy nhớ: Mỗi Shard đều tiêu tốn Heap Memory của RAM, dù nó có chứa dữ liệu hay đang rỗng! Nếu bạn có quá nhiều Shards trên 1 Node, Master Node sẽ bị quá tải khi quản lý trạng thái cụm, và JVM Heap sẽ bị cạn kiệt chỉ để nuôi các tiến trình Shard đang ngủ.
Công thức Sizing Shards chuẩn:
-
Giới hạn số lượng: Một quy tắc an toàn là duy trì tối đa 20 Shards cho mỗi 1GB Heap Memory. Nếu Node của bạn có 30GB Heap, nó chỉ nên chứa tối đa
30 x 20 = 600Shards. -
Kích thước vật lý của 1 Shard:
-
Với dữ liệu Search (E-commerce): Shard nên giữ ở mức 10GB - 20GB để đảm bảo thời gian phục hồi cực nhanh khi rớt Node và load vào RAM dễ dàng.
-
Với dữ liệu Log (Time-series): Shard có thể phình to từ 40GB - 50GB. (Chính là con số
max_size: "50gb"chúng ta đã cấu hình trong ILM Policy ở Bài 41).
-
4. Công thức tính tổng dung lượng ổ cứng (Disk Sizing)
Khi sếp hỏi: "Dự án AFC mỗi ngày sinh ra 10GB log gốc (raw JSON). Cần mua server có ổ cứng bao nhiêu để lưu trữ trong 30 ngày?"
Đừng vội lấy 10GB x 30 ngày = 300GB. Trong Elasticsearch, dữ liệu được Index sẽ nở ra, cộng thêm Replica, cộng thêm khoảng trống an toàn.
Công thức tính Storage dự kiến:
Total Disk = (Raw Data * (1 + Replica Count)) * Indexing Overhead / Watermark
-
Raw Data: 10GB x 30 ngày = 300GB.
-
Replica Count: Thường là 1 (Để đảm bảo High Availability). Tổng dữ liệu =
300 * (1+1) = 600GB. -
Indexing Overhead (Hệ số nở): Dữ liệu JSON khi biến thành Inverted Index thường lớn hơn một chút. Tỷ lệ an toàn là
1.1(Tăng thêm 10%). Tổng =600 * 1.1 = 660GB. -
Watermark (Ngưỡng an toàn HĐH): Elasticsearch sẽ ngừng ghi dữ liệu nếu ổ cứng đầy quá 85% (Low Watermark). Nghĩa là bạn chỉ được dùng 85% dung lượng mua về. Tổng =
660 / 0.85 = 776GB.
Kết luận nộp sếp: Để lưu 10GB log/ngày trong 30 ngày an toàn, cần ổ cứng ít nhất 800GB. (Gấp 2.6 lần so với tính toán thô sơ).
Sizing đúng là bạn đã xây xong một nền móng vững chắc. Tuy nhiên, dù cấu hình có mạnh đến đâu, nếu luồng dữ liệu từ cơ sở dữ liệu gốc (như MySQL/PostgreSQL) đổ về Elasticsearch bị gián đoạn, chắp vá, hoặc delay, thì hệ thống vẫn thất bại.
Ở bài học tiếp theo, chúng ta sẽ bắt đầu bước vào Phần 8: Ứng dụng Thực tế & Tích hợp. Đây là lúc chúng ta ghép nối các hệ thống lại với nhau. Và bài toán đầu tiên sẽ là bài toán kinh điển nhất của Backend Engineer: Đồng bộ dữ liệu Realtime.
All rights reserved