Why ES Fast
Là một Senior Backend Engineer, bạn có thể hình dung tốc độ của Elasticsearch (ES) không đến từ một "phép màu" đơn lẻ, mà là sự kết hợp giữa cấu trúc dữ liệu tinh vi, kiến trúc hệ thống phân tán, và việc tận dụng triệt để cơ chế của OS.
Dưới đây là các tầng lý do chính, đi từ mức dữ liệu (Data) đến mức hệ thống (System):
1. Cấu trúc dữ liệu tối ưu cho việc "Đọc" (Read-Optimized)
ES chấp nhận hy sinh tốc độ ghi (Write latency) và dung lượng lưu trữ để đổi lấy tốc độ đọc cực nhanh.
Inverted Index (cho Text): Như đã bàn ở phần trước, nó biến việc tìm kiếm từ (scan toàn bộ văn bản) xuống gần như hoặc tùy vào độ lớn từ điển.
Finite State Transducer (FST): Để giữ
Term Index(mục lục của từ điển) nhỏ gọn trong RAM, Lucene dùng FST. Nó nén các tiền tố giống nhau của từ (ví dụ: "Go", "Golang", "Google" đều chung gốc "Go"). Nhờ FST, ES có thể giữ index của hàng TB dữ liệu chỉ với vài trăm MB RAM.BKD Trees (cho Numerics & Geo): Trước đây ES dùng Inverted Index cho cả số, nhưng rất chậm khi query range. Hiện tại ES dùng BKD Trees (Block K-dimensional Trees - tương tự QuadTree/R-Tree). Cấu trúc này giúp việc tìm kiếm theo phạm vi (Range query:
price > 100haytimestamp < now) nhanh hơn rất nhiều so với B-Tree truyền thống trong RDBMS.
2. Tận dụng Filesystem Cache của OS (The "Secret Sauce")
Đây là lý do quan trọng nhất mà ít tài liệu cơ bản nhắc tới.
Elasticsearch rất "lười" quản lý bộ nhớ: Thay vì cố gắng tự quản lý bộ nhớ đệm phức tạp như Oracle hay SQL Server, ES phó mặc việc cache các file index (trên đĩa) cho Kernel của Linux (Page Cache).
Cơ chế
mmap(Memory Mapped Files): ES map các file index trên đĩa trực tiếp vào không gian địa chỉ ảo (Virtual Address Space) của process.Khi bạn query, ES truy cập dữ liệu giống như đang đọc trực tiếp từ RAM.
Nếu dữ liệu đã có trong Filesystem Cache, tốc độ là tốc độ RAM (nanoseconds).
Đó là lý do khi vận hành ES, người ta thường khuyên dành 50% RAM cho Heap (Java) và để lại 50% RAM trống hoàn toàn cho OS cache.
3. Kỹ thuật Bitset & Caching thông minh
Khi bạn thực hiện các câu lệnh filter (ví dụ: tìm user active=true VÀ role=admin), ES không so sánh từng dòng.
Bitwise Operations: ES tạo ra các "Bitset" (chuỗi 0 và 1) đại diện cho kết quả.
Doc 1 khớp
active:1Doc 2 không khớp:
0Việc kết hợp điều kiện chỉ là phép toán logic
AND/ORtrên các chuỗi bit này. CPU xử lý việc này cực nhanh.
Roaring Bitmaps: ES nén các chuỗi bit này bằng thuật toán Roaring Bitmaps để tiết kiệm RAM mà vẫn giải nén nhanh.
Query Cache: Các kết quả của
filtercontext được cache lại (LRU cache). Nếu user khác query cùng điều kiện filter, kết quả trả về tức thì mà không cần tính toán lại.
4. Kiến trúc phân tán (Scatter/Gather)
Khả năng Scale-out giúp ES xử lý dữ liệu lớn nhanh hơn RDBMS đơn lẻ:
Sharding (Phân mảnh): Một Index 100GB có thể chia thành 5 Shards, mỗi Shard 20GB nằm trên 1 node khác nhau.
Parallel Execution: Khi có query, node nhận request (Coordinator Node) sẽ gửi lệnh tìm kiếm song song đến tất cả các Shards. Các Shards tự tìm kiếm cục bộ, trả kết quả về Coordinator để tổng hợp (Reduce).
-> Ví dụ: Tìm trong 100GB dữ liệu trên 5 máy (mỗi máy 20GB) sẽ nhanh hơn tìm trên 1 máy chứa 100GB.
5. Immutability (Tính bất biến của Segment)
Dữ liệu trong Lucene được lưu dưới dạng các Segment (phân đoạn). Khi một segment được viết xuống đĩa, nó là bất biến (không bao giờ bị sửa đổi).
Lock-free: Vì không ai có thể sửa file đang đọc, ES không cần cơ chế Locking phức tạp (như Row-level locking trong SQL) khi đọc. Điều này giúp tăng concurrency (khả năng đáp ứng đồng thời) lên cực cao.
Cache Friendly: Vì file không đổi, OS Cache không bao giờ bị invalidate (làm mất hiệu lực) cho đến khi file đó bị xóa.
Tóm lại
Elasticsearch nhanh vì nó tổ chức dữ liệu để đọc ngay từ đầu (Inverted Index, BKD Trees), tính toán bằng toán học cấp thấp (Bitsets), và đứng trên vai người khổng lồ (Linux Filesystem Cache) thay vì cố gắng phát minh lại cái bánh xe quản lý bộ nhớ.
Last updated