- Kiến Trúc Tổng Quan: Ba Cột Trụ Của Hệ Thống
- Tầng Lưu Trữ: LMDB và Heed — Bản Đồ Bộ Nhớ Thay Vì Đọc Ghi Truyền Thống
- Tại Sao Meilisearch Chọn LMDB?
- Heed: Lớp Bọc Rust An Toàn Kiểu Cho LMDB
- Đặc Điểm Lưu Trữ và Quản Lý Không Gian Đĩa
- Tầng Tokenization: Charabia và Nghệ Thuật Phân Tách Ngôn Ngữ
- Tokenizer Là Gì Và Tại Sao Quan Trọng?
- Quy Trình Tokenization: Phát Hiện Script và Áp Dụng Pipeline
- Segmentation và Normalization: Hai Trụ Cột Của Xử Lý Ngôn Ngữ
- Tùy Chỉnh Tokenization: Separator, Non-Separator và Dictionary
- Tầng Lập Chỉ Mục: Inverted Index và Cấu Trúc Dữ Liệu Bên Trong
- Inverted Index: Trái Tim Của Tìm Kiếm Full-Text
- Multi-Threaded Indexing và Tối Ưu Hóa Cập Nhật Từng Trường
- Vector Store và HNSW: Tìm Kiếm Ngữ Nghĩa Bên Trong LMDB
- Tầng Xếp Hạng: Bucket Sort Thay Vì BM25
- Vấn Đề Với BM25 Trong Tìm Kiếm Ứng Dụng
- Bucket Sort Đa Tiêu Chí: Triết Lý Xếp Hạng Của Meilisearch
- Bảy Rule Xếp Hạng Mặc Định
- Tại Sao Bucket Sort Tốt Hơn Cho Application Search?
- Tầng Tìm Kiếm: Hybrid Search và Kết Hợp Keyword với Semantic
- Thuật Toán Kết Hợp Kết Quả Keyword và Vector
- Auto-Embeddings và Tích Hợp AI Provider
- Tầng Mở Rộng: Sharding, Replication và Tương Lai
- Horizontal Scaling Qua Sharding
- RAG và Conversational Search
- Kết Luận: Triết Lý Kiến Trúc Đằng Sau Meilisearch
Kiến Trúc Tổng Quan: Ba Cột Trụ Của Hệ Thống
Meilisearch được thiết kế xung quanh ba trụ cột: hiệu suất, độ liên quan và trải nghiệm nhà phát triển. Cấu trúc mã nguồn của Meilisearch được phân chia thành ba phần chính: repository meilisearch đóng vai trò lớp HTTP API và quản lý nhiều index; milli là engine lõi xử lý tìm kiếm và lập chỉ mục; và Charabia là thư viện tokenizer chuyên xử lý đa ngôn ngữ. Sự phân tách này cho phép mỗi thành phần được tối ưu hóa riêng biệt, đồng thời duy trì giao diện rõ ràng giữa các lớp.
Repository chính meilisearch chỉ chịu trách nhiệm tiếp nhận request HTTP, quản lý nhiều index đồng thời và xử lý update store — nơi lưu trữ các tác vụ bất đồng bộ. Tất cả logic tìm kiếm thực sự và lập chỉ mục được ủy thác cho milli. Điều này có nghĩa là nếu bạn muốn hiểu cách Meilisearch hoạt động bên trong, bạn cần tập trung vào milli và Charabia. Meilisearch được viết hoàn toàn bằng Rust, một ngôn ngữ lập trình hệ thống mang lại sự cân bằng giữa hiệu suất gần với C/C++ và an toàn bộ nhớ compile-time thông qua ownership model. Điều này loại bỏ toàn bộ lớp lỗi liên quan đến use-after-free, double-free và buffer overflow mà các search engine viết bằng C/C++ thường gặp phải.
Tầng Lưu Trữ: LMDB và Heed — Bản Đồ Bộ Nhớ Thay Vì Đọc Ghi Truyền Thống
Tại Sao Meilisearch Chọn LMDB?
Meilisearch sử dụng Lightning Memory-Mapped Database (LMDB) làm engine lưu trữ bên dưới. LMDB là một key-value store giao dịch được viết bằng C, ban đầu phát triển cho OpenLDAP, và có các thuộc tính ACID. Meilisearch đã cân nhắc các lựa chọn khác như Sled và RocksDB, nhưng cuối cùng chọn LMDB vì sự kết hợp tốt nhất giữa hiệu suất, độ ổn định và tính năng. Điểm cốt lõi của LMDB là cơ chế memory mapping: thay vì đọc dữ liệu từ đĩa vào bộ nhớ qua system call read, LMDB ánh xạ trực tiếp file dữ liệu vào không gian địa chỉ ảo của tiến trình. Khi Meilisearch yêu cầu một document, dữ liệu được trả về trực tiếp từ memory map mà không cần cấp phát bộ nhớ hay sao chép dữ liệu.
Kết quả là tất cả document lưu trên đĩa được tự động nạp vào bộ nhớ khi Meilisearch yêu cầu. Điều này đảm bảo LMDB luôn tận dụng tối đa RAM có sẵn để truy xuất document. Tỷ lệ RAM trên đĩa khoảng 1/3 không ảnh hưởng đáng kể đến hiệu suất, và với nhiều workload thậm chí tỷ lệ 1/10 vẫn hoạt động tốt. Điều quan trọng là Meilisearch sẽ không crash khi kích thước dữ liệu trên đĩa vượt quá RAM khả dụng — hệ điều hành sẽ quản lý việc nạp và thay thế các trang bộ nhớ một cách trong suốt. Tuy nhiên, độ trễ đĩa vẫn quan trọng: sử dụng ổ đĩa NVMe SSD cho kết quả tốt hơn đáng kể so với HDD hay lưu trữ mạng.
Heed: Lớp Bọc Rust An Toàn Kiểu Cho LMDB
Meilisearch không sử dụng LMDB trực tiếp qua FFI thô sơ. Thay vào đó, team đã phát triển heed — một crate Rust cung cấp wrapper kiểu an toàn (fully typed) cho LMDB với overhead tối thiểu. Heed cho phép lưu trữ và truy xuất các kiểu dữ liệu Rust trực tiếp trong LMDB, hỗ trợ cả các kiểu tương thích với Serde. Điều này có nghĩa là thay vì làm việc với raw bytes, bạn có thể định nghĩa database với kiểu key và value cụ thể, và Rust sẽ đảm bảo tính đúng đắn tại compile time.
Heed hỗ trợ cả hai nhánh LMDB: mdb.master (qua crate heed) và mdb.master3 (qua crate heed3). Nhánh master3 bổ sung tính năng mã hóa dữ liệu tại chỗ (encryption-at-rest) và checksumming — điều mà heed tiêu chuẩn không có. Cả hai crate chia sẻ cùng một codebase và có thể chuyển đổi qua script convert-to-heed3.sh. Việc sử dụng heed thay vì raw LMDB bindings mang lại lợi ích lớn: transaction an toàn kiểu, iterator typed, và khả năng mở nhiều database con trong cùng một environment mà không cần quản lý raw pointers.
Đặc Điểm Lưu Trữ và Quản Lý Không Gian Đĩa
Một đặc điểm quan trọng của LMDB mà người dùng Meilisearch cần hiểu là cách quản lý không gian đĩa khi xóa document. Khi bạn xóa document khỏi index, dung lượng đĩa có thể không giảm. Điều này xảy ra vì LMDB đánh dấu không gian đó là tự do nội bộ nhưng không trả lại cho hệ điều hành. Thiết kế này mang lại hiệu suất tốt hơn vì không cần thao tác compaction định kỳ, nhưng kết quả là dung lượng đĩa của Meilisearch có xu hướng tăng dần theo thời gian. Không thể tính toán chính xác dung lượng tối đa mà một instance Meilisearch có thể chiếm.
Về mặt kích thước cơ sở dữ liệu, với bộ dữ liệu movies.json khoảng 8.6 MB chứa 19,553 document, sau khi lập chỉ mục kích thước LMDB là khoảng 224 MB trên đĩa và sử dụng khoảng 305 MB RAM. Virtual memory được cấp phát lên đến 205 GB (memory map), nhưng đây chỉ là không gian địa chỉ ảo, không phải bộ nhớ thực sự đang sử dụng. Các con số này phụ thuộc nhiều vào máy chủ đang chạy và rất khó dự đoán chính xác vì kích thước database bị ảnh hưởng bởi settings, ranking rules, facets, số lượng ngôn ngữ và nhiều yếu tố khác.
Tầng Tokenization: Charabia và Nghệ Thuật Phân Tách Ngôn Ngữ
Tokenizer Là Gì Và Tại Sao Quan Trọng?
Tokenization là bước đầu tiên và quan trọng nhất trong quá trình lập chỉ mục document. Đây là hành động lấy một câu hoặc cụm từ và chia nó thành các đơn vị ngôn ngữ nhỏ hơn gọi là token. Khi bạn lập chỉ mục document chứa “Freshly baked croissants”, Meilisearch chia nó thành ba token: freshly, baked, croissants. Các token này là những gì Meilisearch lưu trữ và so khớp khi người dùng thực hiện truy vấn. Việc chia câu thành các phần nhỏ hơn đòi hỏi hiểu biết về nơi một từ kết thúc và từ khác bắt đầu, làm cho tokenization trở thành nhiệm vụ phức tạp và phụ thuộc nhiều vào ngôn ngữ.
Meilisearch giải quyết vấn đề này bằng một tokenizer mô-đun tuân theo các quy trình khác nhau, gọi là pipelines, dựa trên ngôn ngữ mà nó phát hiện. Điều này cho phép Meilisearch hoạt động với nhiều ngôn ngữ khác nhau mà không cần cấu hình. Charabia là thư viện tokenizer mã nguồn mở được viết bằng Rust, được xây dựng chuyên biệt cho mục đích đa ngôn ngữ của Meilisearch.
Quy Trình Tokenization: Phát Hiện Script và Áp Dụng Pipeline
Quy trình tokenization của Meilisearch được thực hiện qua hai bước chính. Bước đầu tiên, tokenizer duyệt qua document và chia mỗi trường theo hệ thống chữ viết (script) — ví dụ: bảng chữ cái Latin, chữ Hán, chữ Cyrillic. Bước thứ hai, nó quay lại từng phần và chạy pipeline tokenization tương ứng nếu có. Mỗi pipeline bao gồm nhiều thao tác chuyên biệt theo ngôn ngữ.
Hiện tại Charabia có các pipeline chuyên dụng cho: Latin (bao gồm tiếng Anh, Pháp, Tây Ban Nha, Ý, Bồ Đào Nha, v.v.), tiếng Đức (với phân tách từ ghép), tiếng Trung (sử dụng jieba dictionary segmentation), tiếng Nhật (lindera IPA dictionary), tiếng Hàn (lindera KO dictionary), tiếng Thái (dựa trên từ điển), tiếng Khmer, tiếng Ả Rập (với phân tách article ال), tiếng Do Thái, tiếng Hy Lạp, tiếng Thổ Nhĩ Kỳ, tiếng Armenia, tiếng Ba Tư và tiếng Thụy Điển. Các ngôn ngữ không có pipeline chuyên dụng vẫn hoạt động với pipeline mặc định dựa trên khoảng trắng, mặc dù kết quả có thể kém liên quan hơn đối với các ngôn ngữ không dùng khoảng trắng để phân tách từ.
Segmentation và Normalization: Hai Trụ Cột Của Xử Lý Ngôn Ngữ
Hai khía cạnh chính trong việc cải thiện hỗ trợ ngôn ngữ là segmentation và normalization. Segmentation là việc hiểu nơi một từ bắt đầu và kết thúc. Điều này tưởng chừng đơn giản với tiếng Anh hay các ngôn ngữ châu Âu — “chia theo khoảng trắng và bạn có từ của mình” — nhưng trở nên phức tạp với tiếng Trung, nơi không có dấu phân cách rõ ràng giữa các ký tự. Normalization bao gồm các sửa đổi chuẩn hóa (chữ hoa/chữ thường), tương đương tương thích (nhận ra cùng một ký tự dưới các dạng khác nhau, ví dụ ツ và ッ), và chuyển tự (chuyển từ bảng chữ cái này sang bảng chữ cái khác).
Ví dụ cụ thể: khi người dùng gõ “mais” trong tiếng Pháp, Meilisearch sẽ trả về kết quả cho cả “but” và “corn” vì nó tính đến khả năng người dùng quên hoặc không sử dụng dấu phù hợp. Đối với tiếng Việt, tokenizer loại bỏ dấu thanh trong quá trình normalization, cho phép tìm kiếm “học sinh” khớp với cả “học sinh” và “hoc sinh”. Tuy nhiên, điều này cũng có thể gây ra vấn đề khi dấu thanh thay đổi nghĩa của từ — đây là một trong những thách thức mà team Meilisearch đang nghiên cứu để cải thiện.
Tùy Chỉnh Tokenization: Separator, Non-Separator và Dictionary
Meilisearch cung cấp ba cài đặt để kiểm soát cách văn bản được chia thành token. Separator tokens cho phép thêm các ký tự hoặc chuỗi tùy chỉnh làm dấu phân cách. Ví dụ, nếu dataset sử dụng | làm delimiter, bạn có thể thêm nó để Meilisearch xử lý “red|green|blue” thành ba token riêng biệt. Non-separator tokens làm ngược lại: ngăn các ký tự như + hay # hoạt động như dấu phân cách, hữu ích cho các thuật ngữ lập trình như C++ hay C#. Dictionary cho phép định nghĩa ranh giới từ tùy chỉnh cho các chuỗi mà Meilisearch không tự chia đúng, ví dụ thêm “icecream” để nó được xử lý như “ice cream”.
Tầng Lập Chỉ Mục: Inverted Index và Cấu Trúc Dữ Liệu Bên Trong
Inverted Index: Trái Tim Của Tìm Kiếm Full-Text
Sau khi tokenization hoàn tất, Meilisearch xây dựng inverted index — cấu trúc dữ liệu cốt lõi của mọi search engine full-text. Inverted index ánh xạ mỗi token duy nhất đến danh sách các document chứa token đó, cùng với metadata như vị trí xuất hiện trong document. Thay vì quét toàn bộ collection để tìm document chứa từ khóa, search engine chỉ cần tra cứu token trong inverted index và lấy danh sách document ID tương ứng.
Meilisearch lưu trữ inverted index trong LMDB dưới dạng các key-value pairs. Key là token đã được normalize, và value là danh sách các document ID cùng với thông tin vị trí (position). Cấu trúc này cho phép tra cứu cực nhanh: với mỗi token trong truy vấn, Meilisearch chỉ cần một lần đọc từ LMDB để lấy toàn bộ danh sách document liên quan. Khi có nhiều token trong truy vấn, engine thực hiện phép giao (intersection) hoặc hợp (union) các danh sách posting tùy thuộc vào toán tử tìm kiếm.
Multi-Threaded Indexing và Tối Ưu Hóa Cập Nhật Từng Trường
Một trong những cải tiến đáng chú ý gần đây của Meilisearch là tối ưu hóa tốc độ lập chỉ mục. Khi cập nhật một trường nhỏ trong document, thay vì lập chỉ mục lại toàn bộ document, Meilisearch chỉ lập chỉ mục lại trường đã thay đổi. Điều này giảm đáng kể thời gian xử lý và tài nguyên hệ thống, đặc biệt quan trọng cho các ứng dụng thương mại điện tử cần cập nhật số lượng tồn kho theo thời gian thực. Quá trình lập chỉ mục được thực hiện đa luồng (multi-threaded), tận dụng toàn bộ sức mạnh CPU để xử lý song song các document và token.
Vector Store và HNSW: Tìm Kiếm Ngữ Nghĩa Bên Trong LMDB
Khi tích hợp semantic search, Meilisearch không sử dụng một vector database riêng biệt. Thay vào đó, nó lưu trữ embeddings ngay trong LMDB cùng với dữ liệu document. Để tìm kiếm vector hiệu quả, Meilisearch sử dụng thuật toán HNSW (Hierarchical Navigable Small World) — một cấu trúc đồ thị xấp xỉ lân cận gần (Approximate Nearest Neighbor) cho phép tìm kiếm vector với độ phức tạp logarithmic.
HNSW xây dựng một đồ thị phân tầng trong đó mỗi tầng là một đồ thị xấp xỉ lân cận thưa thớt hơn tầng dưới. Tìm kiếm bắt đầu từ tầng cao nhất, đi xuống tầng thấp hơn khi đã tìm thấy điểm gần nhất trong tầng hiện tại, và cuối cùng tìm kiếm chi tiết trong tầng thấp nhất. Cách tiếp cận này cho phép Meilisearch tìm kiếm hàng triệu vector trong vòng mili giây mà không cần quét toàn bộ không gian vector. Đáng chú ý, Meilisearch đã tối ưu hóa việc triển khai HNSW trên LMDB bằng cách sử dụng nested read transactions và thread-local storage, giúp tăng tốc độ vector store lên gấp 3 lần.
Tầng Xếp Hạng: Bucket Sort Thay Vì BM25
Vấn Đề Với BM25 Trong Tìm Kiếm Ứng Dụng
Hầu hết các search engine truyền thống xếp hạng kết quả bằng cách tính một điểm số duy nhất cho mỗi document, sau đó sắp xếp theo số đó. BM25 — tiêu chuẩn công nghiệp cho full-text search — tính điểm dựa trên tần suất thuật ngữ (TF), tần suất nghịch đảo document (IDF) và chuẩn hóa độ dài document. PostgreSQL ts_rank, MongoDB Atlas Search, Elasticsearch và OpenSearch đều sử dụng các biến thể của mô hình này.
Tuy nhiên, BM25 được thiết kế cho information retrieval — tìm kiếm bài báo nghiên cứu, tài liệu pháp lý hay trang web — nơi tần suất thuật ngữ thực sự báo hiệu độ liên quan. Nhưng đối với application search (thương mại điện tử, catalog phương tiện, dashboard SaaS), mô hình này gặp nhiều hạn chế: typo hoàn toàn vô hình với BM25 — “iPhone” và “iPhoone” được xử lý như hai thuật ngữ hoàn toàn khác nhau; thứ tự từ bị bỏ qua — tìm “dark knight” và “knight dark” cho cùng một điểm số; mức độ quan trọng của trường bị san phẳng — match trong tiêu đề sản phẩm nên quan trọng hơn match trong bình luận, nhưng BM25 đòi hỏi điều chỉnh trọng số thủ công phức tạp; và điểm số là mờ đục — điểm 8.72 không nói lên điều gì cho developer đang debug tại sao kết quả A xuất hiện trước kết quả B.
Bucket Sort Đa Tiêu Chí: Triết Lý Xếp Hạng Của Meilisearch
Meilisearch thay thế mô hình điểm số đơn lẻ bằng hệ thống multi-criteria bucket sort. Thay vì tính một con số, engine đánh giá document qua một chuỗi các ranking rules, mỗi rule đóng vai trò như một bộ lọc liên tiếp. Khi người dùng tìm kiếm “badman dark knight returns”, Meilisearch áp dụng các rule theo thứ tự:
Rule đầu tiên, words, sắp xếp document theo số lượng từ truy vấn khớp — document chứa cả 4 từ vào Bucket A, 3 từ vào Bucket B, 1 từ vào Bucket C. Rule thứ hai, typo, chỉ áp dụng cho các document trong cùng một bucket — 0 typo vào sub-bucket A.1, 1 typo vào A.2. Rule thứ ba, proximity, xem xét khoảng cách giữa các từ khớp — các từ liền kề vào A.1.1, cách xa 3 từ vào A.1.2. Cứ tiếp tục như vậy qua attributeRank, sort, wordPosition và cuối cùng exactness.
Mỗi rule chỉ hoạt động trên các document đã hòa trong tất cả các rule trước đó. Điều này có nghĩa là một document khớp 4/4 từ với 2 typo luôn xếp trên document khớp 3/4 từ với 0 typo. Rule words có ưu tiên tuyệt đối trên typo, typo trên proximity, v.v. Không có cách nào để điểm cao ở một chiều bù đắp cho điểm thấp ở chiều khác. Đây được gọi là lexicographic ordering — cùng logic mà con người dùng để sắp xếp từ trong từ điển, được áp dụng vào xếp hạng tìm kiếm.
Bảy Rule Xếp Hạng Mặc Định
Meilisearch có bảy rule xếp hạng built-in theo thứ tự mặc định. Words sắp xếp theo số lượng từ truy vấn khớp giảm dần, hoạt động từ phải sang trái nên thứ tự chuỗi truy vấn ảnh hưởng đến thứ tự kết quả. Typo sắp xếp theo số lượng typo tăng dần, với tối đa 2 typo cho mỗi từ truy vấn. Proximity sắp xếp theo khoảng cách giữa các từ khớp giảm dần — “dark knight” liền kề luôn xếp trên “dark … knight” cách xa. AttributeRank sắp xếp theo thứ tự độ quan trọng của attribute — match trong title luôn xếp trên match trong description nếu title được đặt trước trong searchableAttributes. Sort chỉ kích hoạt khi query có tham số sort. WordPosition sắp xếp theo vị trí từ khớp trong attribute — xuất hiện ở đầu trường xếp trên cuối trường. Exactness sắp xếp theo độ tương đồng chính xác — “knight” khớp chính xác xếp trên “knights” (prefix match).
Bạn có thể sắp xếp lại, thêm hoặc xóa bất kỳ rule nào. Bạn cũng có thể thêm custom ranking rules như popularity:desc hay release_date:desc để đưa logic kinh doanh vào xếp hạng. Thứ tự của các rule quyết định tiêu chí nào được ưu tiên — rule đầu tiên có tác động lớn nhất, rule cuối cùng có tác động nhỏ nhất.
Tại Sao Bucket Sort Tốt Hơn Cho Application Search?
So với BM25, hệ thống bucket sort của Meilisearch có nhiều ưu điểm rõ ràng cho tìm kiếm ứng dụng. Đầu tiên, typo tolerance được tích hợp sâu — không phải như một bước fuzzy query riêng biệt mà là một tiêu chí xếp hạng first-class. Thứ hai, thứ tự từ và proximity được tôn trọng — “new york pizza” trong cụm liền kề xếp trên “new … york … pizza” phân tán. Thứ ba, mức độ quan trọng của trường là rõ ràng và có thể dự đoán — field đầu tiên trong searchableAttributes luôn thắng field thứ hai, không cần điều chỉnh trọng số phức tạp. Thứ tư, xếp hạng là minh bạch và có thể debug — thông qua showRankingScoreDetails, bạn có thể thấy chính xác tại sao một document xếp ở vị trí nào. Thứ năm, prefix search hoạt động tự nhiên — từ cuối cùng trong query luôn được xử lý như prefix mà không cần cấu hình n-gram hay edge-gram. Cuối cùng, không cần tuning từng query — các rule được cấu hình một lần ở cấp index và hoạt động nhất quán trên mọi truy vấn.
Tầng Tìm Kiếm: Hybrid Search và Kết Hợp Keyword với Semantic
Thuật Toán Kết Hợp Kết Quả Keyword và Vector
Khi bật embedder, Meilisearch kết hợp tìm kiếm dựa trên từ khóa (keyword search qua bucket sort) với tìm kiếm vector similarity trong một query duy nhất. Tham số semanticRatio kiểm soát tỷ lệ pha trộn: 0.0 chỉ sử dụng multi-criteria ranking rules, 1.0 chỉ sử dụng vector similarity, và các giá trị ở giữa hợp nhất cả hai tập kết quả. Điều này mang lại lợi ích kép: độ chính xác của từ khóa kết hợp với khả năng hiểu ngữ nghĩa, mà không cần quản lý hai hệ thống tìm kiếm riêng biệt.
Quy trình hoạt động như sau: khi người dùng gửi truy vấn, Meilisearch chạy đồng thời cả keyword search và semantic search. Keyword search sử dụng inverted index và bucket sort như đã mô tả. Semantic search sử dụng HNSW để tìm các vector embedding gần nhất với vector của truy vấn. Hai tập kết quả sau đó được hợp nhất bằng hệ thống scoring thông minh, và các kết quả liên quan nhất xuất hiện đầu tiên, bất kể chúng khớp bằng từ khóa chính xác hay bằng ý nghĩa ngữ nghĩa.
Auto-Embeddings và Tích Hợp AI Provider
Meilisearch hỗ trợ tự động tạo embeddings thông qua nhiều nhà cung cấp: OpenAI, Cohere, Mistral, Google Gemini, Cloudflare, Voyage AI, Jina, AWS Bedrock và HuggingFace. Khi được cấu hình với một embedder, Meilisearch tự động tạo vector embeddings cho document khi lập chỉ mục và cho truy vấn khi tìm kiếm. Điều này loại bỏ nhu cầu quản lý vector store riêng biệt — embeddings được lưu trữ ngay trong LMDB cùng với dữ liệu document. Nhiều mô hình embedding đa ngôn ngữ có thể xử lý hơn 100 ngôn ngữ, cho phép tìm kiếm xuyên ngôn ngữ: một truy vấn bằng tiếng Anh có thể khớp với document viết bằng tiếng Pháp, Đức hay Nhật.
Tầng Mở Rộng: Sharding, Replication và Tương Lai
Horizontal Scaling Qua Sharding
Phiên bản Enterprise của Meilisearch giới thiệu sharding — khả năng phân phối dữ liệu qua nhiều node. Sharding cho phép xử lý các tập dữ liệu khổng lồ vượt quá khả năng của một máy chủ đơn lẻ. Ngoài ra, replicated sharding đã được tích hợp vào engine, cho phép tìm kiếm phân tán có khả năng chịu lỗi. Khi một node gặp sự cố, các node replica có thể tiếp tục phục vụ request mà không bị gián đoạn. Điều này đánh dấu bước tiến quan trọng trong việc đưa Meilisearch từ giải pháp single-node sang kiến trúc phân tán thực sự.
RAG và Conversational Search
Meilisearch đã mở rộng ra ngoài tìm kiếm truyền thống để hỗ trợ Retrieval-Augmented Generation (RAG). Trong kiến trúc RAG, khi người dùng đặt câu hỏi bằng ngôn ngữ tự nhiên, Meilisearch trước tiên thực hiện hybrid search để tìm các document liên quan nhất. Những document này sau đó được đưa vào prompt của LLM như context, cho phép AI tạo ra câu trả lời dựa trên dữ liệu thực tế của bạn thay vì kiến thức chung. Meilisearch cung cấp kiểm soát chi tiết về nội dung nào được gửi đến LLM — bạn có thể chọn trường nào đưa vào prompt, sử dụng template đơn giản, và bao gồm metadata. Tích hợp với LangChain và MCP (Model Context Protocol) cho phép Meilisearch trở thành lớp retrieval trong pipeline AI một cách liền mạch.
Kết Luận: Triết Lý Kiến Trúc Đằng Sau Meilisearch
Meilisearch là minh chứng cho việc các quyết định kiến trúc sáng suốt có thể tạo ra sản phẩm vượt trội. Bằng cách chọn Rust cho an toàn và hiệu suất, LMDB cho lưu trữ zero-copy, bucket sort thay vì BM25 cho xếp hạng minh bạch, và Charabia cho xử lý đa ngôn ngữ, Meilisearch đã xây dựng một search engine không chỉ nhanh mà còn dễ hiểu và dễ kiểm soát.
Điểm mạnh cốt lõi của kiến trúc này là sự tách biệt rõ ràng giữa các tầng: lưu trữ (LMDB qua heed), tokenization (Charabia), lập chỉ mục (milli inverted index), xếp hạng (bucket sort), và tìm kiếm (hybrid keyword + vector). Mỗi tầng có thể được tối ưu hóa, thay thế hoặc mở rộng độc lập. Điều này giải thích tại sao Meilisearch có thể thêm semantic search, RAG và sharding mà không phá vỡ API hay yêu cầu tái cấu trúc lớn.
Đối với developer, hiểu kiến trúc bên trong Meilisearch giúp đưa ra quyết định thiết kế tốt hơn: khi nào nên chia nhỏ document để proximity hoạt động tốt hơn, cách sắp xếp ranking rules để phản ánh ưu tiên kinh doanh, làm thế nào để cấu hình tokenization cho dữ liệu đặc thù, và khi nào nên tăng RAM so với sharding. Meilisearch không chỉ là một công cụ — nó là một hệ thống mà bạn có thể hiểu sâu, kiểm soát hoàn toàn và tùy chỉnh cho nhu cầu cụ thể của mình.
Bình luận