自架服務 Rust Meilisearch 搜尋引擎 LMDB 向量搜尋

Algolia 按查詢收錢、Elasticsearch 換過授權:Meilisearch 1.41 用 Rust 跟 LMDB 把嵌入式搜尋壓回單台 VPS

Meilisearch 是 Rust 寫的自架搜尋引擎,2026 年 3 月 v1.41 補上 Dynamic Search Rules,把 Algolia 長年獨有的規則排序帶進開源版本。本文拆解它的 milli + LMDB 選擇、hybrid search 的落地、跟 Typesense 的實際差異,以及在 VPS 上該怎麼估規格。

應用程式裡要放搜尋這件事,長期以來只有三條路:接 Algolia 這類 SaaS 付按次搜尋的錢、自架 Elasticsearch 或 OpenSearch 面對整套 JVM 的維運成本、或者直接靠 PostgreSQL 的 tsvector 湊合。前兩條走到中型 SaaS 的量體之後帳單跟機器成本都不小,後者的體驗又長期停在「能用但沒有 typo tolerance」的階段。Meilisearch 是 Rust 寫的開源全文搜尋引擎,從 2020 年開源以來一直在補這一段缺口,2026 年 3 月推進到 v1.41.0,把 Dynamic Search Rules 這個 Algolia 長年獨有的功能也加了進來。

Meilisearch 由同名的法國公司主導,MIT 授權,商業收入來自 Meilisearch Cloud 託管服務。這篇聚焦在自架情境下它跟 Typesense、Elasticsearch 的實際差別,包含 v1.41 的動態排序機制、milli 引擎跟 LMDB 儲存層的取捨,以及在 VPS 上部署該怎麼估算資源。

三條老路的實際成本

Algolia 收費按 record 數量跟每月搜尋次數計價,中型 SaaS 每月帳單很容易落在幾百到幾千美金。這個價錢對「搜尋不是產品核心、只是需要有」的場景不合理,特別是團隊已經有自架 VPS 骨幹跑其他服務時,多養一台跑搜尋通常划算得多。

Elasticsearch 的問題不是貴而是重。JVM 沒有 1GB heap 開不動,2GB 才勉強撐得住生產查詢負載。2021 年授權從 Apache 2.0 換成 Elastic License 2.0 之後,AWS 直接 fork 出 OpenSearch,到 2026 年這條分歧走了 5 年,兩邊的 API 還算相容但已經有裂縫。想避開授權地雷就得選 OpenSearch,但整套心智模型、外掛生態、監控工具都得重新對過。

PostgreSQL 的 tsvector 加 tsquery 能做基本的 stemming 跟排序,設好 GIN index 也有可用的效能。但沒有 typo tolerance、facet 得自己拼、highlight 支援有限、多語言分詞得靠 pg_trgm 補。當搜尋只是資料庫欄位的延伸這條路夠用,要拿去做電商產品檢索或文件搜尋很快就會露底。

milli 加 LMDB 的技術取捨

Meilisearch 沒有直接用 tantivy。Rust 生態裡最成熟的 Lucene 對應物是 tantivy,Quickwit 拿它撐起了自己的 log analytics 產品線。Meilisearch 走了另一條路,自己寫了叫 milli 的 crate,倒排索引直接寫進 LMDB。

這個選擇背後有兩個現實理由。LMDB 是 memory-mapped 資料庫,寫入 durability 靠 mmap 加 msync,讀取靠作業系統的 page cache 自動處理。這個模型下資料集比 RAM 大也能跑——只有被查詢命中的部分會被 page in;重開機不用重建索引;空間管理由 kernel 決定而不是 GC。對「搜尋要壓進小台 VPS」這件事非常合適。

另一個是隔離性。milli 是 embedded 引擎,寫索引跟查詢都在同個 process 內,跟 Elasticsearch 走 network-first 的設計相反,網路 hop 全部省掉。這也是 Meilisearch 能壓進 512MB RAM 的核心原因。

代價是 LMDB 的寫入模型是 single writer——同時只能有一筆 transaction 在寫。對搜尋負載這通常不是問題,寫入本來就是背景 batch,查詢才是熱路徑。但如果應用場景是持續高頻寫入(例如把 Meilisearch 當 log store 用),這個瓶頸會馬上出現。

向量搜尋從 v1.3 補到 v1.41

Meilisearch 對 semantic search 的支援分階段進來。v1.3 (2023 年中) 開始支援 vector storage,v1.6 (2023 年底) 正式推出 hybrid search,把 BM25 全文檢索的分數跟 vector cosine similarity 融合。

向量索引用的是 arroy——他們自家寫的 crate,設計靈感來自 Spotify 開源的 annoy,但用 Rust 重寫並改成走 LMDB 儲存。這個決定讓向量索引跟主體共用同一個儲存層,開發跟部署上不用另外拉一個 Qdrant 或 Milvus 進來。單一 API、單一 binary、單一儲存路徑。

Hybrid search 的權重可以在查詢時透過 hybrid.semanticRatio 參數指定,從 0 (純關鍵字) 到 1 (純語意)。內建 embedder 支援 OpenAI、Hugging Face、以及 Ollama 直連——Ollama 這一項對想在自架環境跑本地 embedding 的團隊實用度很高,向量產生跟搜尋可以完全留在機房內。

實務上這組合對 RAG 場景意外好用。單一 API 同時處理關鍵字跟語意檢索,不用另外部署向量資料庫再自己合併分數。做內部文件搜尋、產品目錄、或者 AI Agent 的檢索後端都能吃下。

v1.41 的 Dynamic Search Rules 補上關鍵缺口

Meilisearch 過去被詬病的地方是排序客製化不如 Algolia 靈活。Algolia 的 Rules 系統讓運營端可以針對特定查詢字串置頂特定商品、遮蔽敏感詞、或根據時段調整結果順序。Meilisearch 到 v1.40 之前只能做 sort 這種欄位排序,複雜的商業邏輯得在應用層自己拼。

v1.41 加進來的 Dynamic Search Rules (DSR) 讓這件事有了官方解法。規則由「條件」跟「動作」組成——條件目前支援空查詢、literal 子字串出現、以及時間窗;動作是 pin document,可以指定多份文件的順序。以節慶場景為例,黑色星期五當週要把特價商品置頂、平常日按預設排序,就是一組 DSR 規則加上時間窗條件。

API 是 REST:PATCH /dynamic-search-rules/{uid} 建立或更新,DELETE /dynamic-search-rules/{uid} 移除。release note 特別註明 pin 會跟 filtering、pagination、facet distribution、hybrid search、federated search 這些既有功能相容——這件事寫進 spec 表示他們有花時間處理 query pipeline 之間的交互。

功能還是 experimental,得在啟動時打開 --experimental-dynamic-search-rules flag。生產環境用之前值得等一兩個小版本讓 API 穩定,特別是條件類型後續會擴充(filter 條件、facet 條件都在 roadmap 上)。

Typesense 全記憶體 vs Meilisearch 磁碟對映

Typesense 是 Meilisearch 最直接的對手。同樣是 SaaS 級 developer experience、同樣走簡單 REST API、同樣強調 typo tolerance。但底層設計差很多,這個差別決定了兩者適合的場景。

Typesense 把整個 index 塞進 RAM。這帶來 sub-50ms 的查詢延遲跟內建的 Raft-based clustering,代價是 10GB 資料集就需要 10GB RAM。適合搜尋 QPS 很高、資料集規模可控、預算允許堆記憶體的場景——多租戶 SaaS、廣告檢索這類。

Meilisearch 走 LMDB memory-mapped 的路,讓資料集能比 RAM 大。512MB RAM 的 VPS 可以撐 5GB 索引,代價是首次冷查詢會慢一點——OS 得先 page in 相關的檔案區塊。只要熱區資料能 fit 進 page cache,實際延遲跟 Typesense 差距對使用者感受不會太明顯。

決策點其實蠻清楚:搜尋 QPS 超過 5K 而且資料集在 10GB 以內,Typesense 的 all-RAM 設計划算;QPS 幾百到幾千、資料集可能長到 20-50GB,Meilisearch 更省成本。Typesense 內建 clustering、Meilisearch 沒有——這是選 Typesense 的另一個理由,如果 HA 是硬需求。Meilisearch 的 HA 目前得靠外部 load balancer 加主從架構自己拼,v1.x 週期還沒把 replication 做進 core。

VPS 上跑起來的實際規格

Meilisearch 的資源需求跟資料集大小、QPS、以及是不是開了 vector search 都有關。三個常見規模的參考。

輕量部署(部落格、文件站搜尋,5 萬筆文件以下、QPS 個位數):512MB RAM、2 vCPU、10GB SSD 就夠。這個規格連 vector search 都吃得下,只要 embedding 模型跑在別台機器。

中型部署(電商產品搜尋,100 萬筆文件、QPS 幾百):2GB RAM、4 vCPU、50GB NVMe SSD。索引跟熱區能 fit 進 page cache,冷查詢也能靠 NVMe 的 IOPS 撐住 sub-100ms 延遲。

大型部署(SaaS 多租戶,幾千萬筆文件、QPS 上千):4-8GB RAM、8 vCPU、100GB 以上 NVMe。到這個規模就要開始評估 sharding——Meilisearch 的做法是 multi-index,把不同租戶或不同資料類型分到不同 index,這是最直接的水平擴充路徑。

磁碟這件事 NVMe 幾乎是必備。SATA SSD 撐 100 萬筆文件以上會開始感覺 indexing 慢,LMDB 的寫入 pattern 對隨機 IOPS 敏感,機械硬碟直接放棄。

什麼場景不該選 Meilisearch

Log aggregation 跟 APM 這種時序型負載不合適。Meilisearch 沒有 rollover index、沒有 hot/cold tier、也沒有針對時間排序的儲存優化——這是 Elasticsearch、OpenSearch、VictoriaLogs、ClickHouse 的地盤。硬拿 Meilisearch 撐 log search 只會被 index 大小炸爆,官方也沒把這條路線列進 roadmap。

超過 1 億筆文件的單一 index 也不建議。這個規模的 indexing throughput 跟磁碟佔用會退化明顯,官方的 sweet spot 一直是百萬到千萬筆。真的有這種資料量就得回頭考慮 Elasticsearch 或 OpenSearch 的 sharding 模型,或者用 Meilisearch 的 multi-index 把資料切碎分散。

複雜聚合分析同樣不是 Meilisearch 的強項。它有 facet distribution 但沒有 aggregation pipeline,算不出滾動平均、histogram、time series bucket——這些屬於 OLAP 引擎的工作,Doris、ClickHouse、DuckDB 才是對的工具。

Cloud serverless 這條路線的分歧

Meilisearch 官方 roadmap 上 2026 Q3 要推 serverless indexes,設計是把 inactive 的 index 搬到 S3 兼容的 object storage,查詢進來才 spin up。這條路對 SaaS 型應用有吸引力——每個租戶一個 index、多數租戶不常查詢的場景,成本可以壓得比 always-on 低很多。

但這個功能會先只在 Meilisearch Cloud 上線。自架版本什麼時候拿到、拿不拿得到,公司目前沒公開表態。對堅持自架的團隊來說這條分歧值得留意——如果未來 Cloud 跟 self-hosted 的功能落差擴大,就得在「換 Cloud」跟「留自架但接受功能差距」之間做選擇。以目前的節奏來看,重要功能還是有進到自架版本,但商業考量會不會改變路線是個變數。

把搜尋留在自家機房這件事

自架搜尋引擎的價值不只在省 SaaS 帳單。使用者的查詢字串本身帶著大量業務資訊——關鍵字揭露意圖、搜尋歷史揭露偏好、失敗查詢揭露產品缺口——把這些資料送給第三方 SaaS 等於把行為分析外包出去。Meilisearch 這種可以壓進單台 VPS 的架構讓「搜尋留在自家機房」變成合理選項,而不是「聽起來很好但沒人真的做」。

跑 Meilisearch 的 VPS 對 CPU 單核心效能跟磁碟 IOPS 都敏感——LMDB 的 mmap 讀取吃 page cache 命中率,寫入吃隨機 IOPS。NCSE Network 在臺灣是方電訊機房提供搭載 Intel Xeon Gold CPU 跟 NVMe SSD 的 VPS 主機,臺灣本地線路對面向國內使用者的搜尋 API 延遲條件穩定,適合 SaaS 搜尋、電商產品檢索、以及自架文件系統這類負載。前往 ncse.tw 了解方案細節。

需要穩定的雲端主機?

NCSE Network 提供企業級 VPS,7 天免費試用,臺灣是方電訊機房,99% SLA 保證。

查看 VPS 方案 →