Skip to content
Gains Summary
Main Navigation 首页 / Home
C++ 编程 / C++ Programming
系统与高性能 / Systems & Performance
Web 开发 / Web Development
人工智能 / Artificial Intelligence
工业软件 / Industrial Software
其他内容 / Other Topics
C++ 编程 / C++系统与性能 / SystemsWeb 开发 / Web人工智能 / AI工业软件 / Industrial

外观

Sidebar Navigation

← Web 开发 / Web Development

中间件 / Middleware

1. Web 中间件全景 / The Web Middleware Landscape

2. 中间件——流量洪峰下的系统保护 / Middleware for Protecting Systems Under Traffic Spikes

cache layer

1. 缓存架构全景 / Cache Architecture Overview

2. Redis 深入——为什么你的缓存总是出问题 / Redis Internals and Cache Failure Modes

3. Redis 数据结构场景应用——什么时候用什么 / Choosing Redis Data Structures for Real Applications

4. 缓存策略——库存变了,缓存怎么处理 / Cache Strategies and Inventory Consistency

5. Redis 缓存三剑客——穿透/击穿/雪崩 + 一致性策略 / Redis Cache Penetration, Breakdown, Avalanche, and Consistency

6. Redis 分布式锁——从 SETNX 到 Redisson / Redis Distributed Locks from SETNX to Redisson

7. Redis Cluster 与 Sentinel 高可用架构 / Redis Cluster and Sentinel High-Availability Architecture

8. Redis 高级特性——Stream / PubSub / Module / LLM 应用

9. Redis 架构深度分析——为什么 Redis 能这么快 / Redis Architecture and the Sources of Its Performance

10. Redis 全景——为什么你的系统需要一个缓存层 / The Redis Landscape and Why Systems Need a Cache Layer

message queue

1. 消息队列全景——为什么你的系统需要一个中间人 / Message Queue Overview and Why Your System Needs a Middleman

2. Kafka 核心——为什么你的消息总是"丢"了 / Kafka Fundamentals and Message Delivery Semantics

3. 消息队列高级——死信队列、延迟消息、消息积压 / Advanced Messaging with Dead Letters, Delays, and Backlogs

4. Kafka Streams 与 Connect —— 让数据自己流动起来 / Kafka Streams and Connect for Streaming Data Pipelines

5. RabbitMQ 深度解析 —— 灵活路由与消息可靠性 / RabbitMQ Deep Dive into Flexible Routing and Reliability

6. 消息队列对比——为什么最终选了 Kafka / Comparing Message Queues and Choosing Kafka

search engine

1. 搜索引擎知识体系 / Search Engine Knowledge System

2. Elasticsearch——为什么 Like 查询总是那么慢 / Elasticsearch for Full-Text Search at Scale

3. Elasticsearch 查询 DSL 深入——为什么你的搜索总是不准 / Elasticsearch Query DSL Deep Dive

4. Elasticsearch 集群规划与运维——为什么你的集群总是"黄" / Elasticsearch Cluster Planning and Operations

5. Meilisearch 与轻量搜索替代方案——当 ES 太重时 / Meilisearch and Lightweight Search Alternatives

infrastructure

1. 基础设施组件全景 / Infrastructure Components Landscape

2. Nginx 与反向代理 / Nginx and Reverse Proxy

3. 服务发现 / Service Discovery

4. 配置中心 / Configuration Center

本页目录

Meilisearch 与轻量搜索替代方案——当 ES 太重时 / Meilisearch and Lightweight Search Alternatives ​

📅 创建时间:2026-07-28 🏷️ 标签:#Meilisearch #Typesense #OpenSearch #PostgreSQL #全文搜索 #选型 #轻量搜索 📚 前置知识:[[./00-overview]](搜索引擎概览) [[./02-elasticsearch-queries]](ES 查询 DSL)


📋 本章目标 ​

  • 理解 Meilisearch 的核心特性及其与 ES 的本质差异
  • 掌握 Meilisearch 的部署、索引配置和搜索 API
  • 能够对比 Meilisearch、Typesense、OpenSearch 的功能矩阵
  • 理解 PostgreSQL 全文搜索的适用场景与局限性
  • 掌握搜索引擎选型的决策树和优先级排序
  • 能够在"轻量体验"和"无限控制"之间做出正确取舍

第1部分:Meilisearch 核心特性 ​

1.1 Meilisearch 是什么 ​

Meilisearch 是一个用 Rust 编写的开源搜索引擎,核心理念是"开箱即用、零配置、即时搜索"。它的定位非常清晰:做 ES 能做但太复杂的那部分事情。

┌─────────────────────────────────────────────────────────────┐
│                    Meilisearch 定位                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Meilisearch = 一个二进制文件,一条命令启动                 │
│                                                             │
│  $ ./meilisearch                                            │
│  → Server is listening on http://127.0.0.1:7700            │
│                                                             │
│  对比 ES:                                                  │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                    Meilisearch          ES             │   │
│  │  ────────────────────────────────────────────────    │   │
│  │  启动方式      一条命令             JVM配置+配置     │   │
│  │  配置文件      无(可选)          elasticsearch.yml │   │
│  │  JVM 调优      不需要(Rust)     Heap + GC 调优    │   │
│  │  中文分词      内置(Jieba)      需要安装插件       │   │
│  │  同义词管理    REST API           配置文件或API      │   │
│  │  排序规则      内置规则引擎       自定义 function_score │   │
│  │  容错/拼写纠错 默认开启           需要 fuzzy query   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

1.2 即时搜索(Search-as-you-type) ​

Meilisearch 的招牌能力是"即时搜索"——用户每输入一个字符,结果立即更新。这不是简单的 prefix 查询,而是多层次的匹配策略。

┌─────────────────────────────────────────────────────────────┐
│                Meilisearch 即时搜索机制                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  用户输入: "app"                                            │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Meilisearch 的匹配策略(按优先级排序):             │   │
│  │                                                      │   │
│  │  1. Typo Tolerance(容错匹配,默认开启)             │   │
│  │     "app" → 匹配 "apple", "apply", "appendix"       │   │
│  │     允许 1-2 个字符的编辑距离差异                    │   │
│  │                                                      │   │
│  │  2. Prefix Search(前缀匹配)                        │   │
│  │     "app" → 匹配 "apple", "application"             │   │
│  │     所有以 "app" 开头的词                            │   │
│  │                                                      │   │
│  │  3. 分词匹配                                         │   │
│  │     "app" → 匹配 "App Store", "web app"             │   │
│  │     当 "app" 作为独立词出现时                        │   │
│  │                                                      │   │
│  │  4. 排序规则(Relevancy Rules)                      │   │
│  │     • 精确匹配 > 前缀匹配 > 容错匹配                │   │
│  │     • 短字段匹配 > 长字段匹配                        │   │
│  │     • 词序匹配 > 乱序匹配                            │   │
│  │     • 标题匹配 > 正文匹配                            │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  与此对比,ES 需要手动配置:                                │
│  - ngram tokenizer / edge ngram                            │
│  - fuzzy query                                             │
│  - multi_match with type and boost                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

1.3 容错与同义词 ​

┌─────────────────────────────────────────────────────────────┐
│                    容错与同义词管理                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  容错(Typo Tolerance)—— 默认开启,无需配置               │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Meilisearch 的容错规则:                             │   │
│  │                                                      │   │
│  │  词长度    允许的编辑距离    举例                    │   │
│  │  ───────────────────────────────────────────         │   │
│  │  1-4       0(不纠错)       "the" 不变             │   │
│  │  5-8       1                 "aple" → "apple"       │   │
│  │  >8        2                 "elastcsear" →          │   │
│  │                              "elasticsearch"         │   │
│  │                                                      │   │
│  │  编辑距离 = Levenshtein distance                     │   │
│  │  (一个字符的增/删/改/换位 = 1 次操作)              │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  同义词 —— 通过 REST API 动态管理                          │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  POST /indexes/products/settings/synonyms           │   │
│  │  {                                                  │   │
│  │    "phone": ["mobile", "cellphone", "smartphone"],  │   │
│  │    "laptop": ["notebook", "macbook"]               │   │
│  │  }                                                  │   │
│  │                                                      │   │
│  │  → 搜索 "mobile" 会自动匹配 "phone" 的文档          │   │
│  │  → 同义词是单向还是双向?→ 单向 (搜索词映射)        │   │
│  │  → 不需要修改索引或重建,即时生效!                  │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  排序规则(Ranking Rules)—— 内置可覆盖                    │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  默认排序规则(优先级从高到低):                     │   │
│  │                                                      │   │
│  │  1. words: 匹配词数(越多越好)                      │   │
│  │  2. typo: 无容错 > 有容错(精确优先)               │   │
│  │  3. proximity: 词距离(越近越好)                    │   │
│  │  4. attribute: 字段重要性(标题 > 正文)            │   │
│  │  5. wordsPosition: 词位置(越靠前越好)              │   │
│  │  6. exactness: 完全匹配 > 部分匹配                   │   │
│  │                                                      │   │
│  │  可自定义添加规则:                                   │   │
│  │  ["words","typo","proximity","price:asc",            │   │
│  │   "release_date:desc","exactness"]                   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

1.4 Meilisearch 实战:文档搜索 ​

┌─────────────────────────────────────────────────────────────┐
│                Meilisearch 完整搜索流程                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  # 1. 启动(Docker)                                        │
│  docker run -p 7700:7700 getmeili/meilisearch:latest \     │
│    meilisearch --master-key="masterKey"                     │
│                                                             │
│  # 2. 创建索引 + 配置可搜索属性                            │
│  POST /indexes                               │   │
│  {"uid": "movies", "primaryKey": "id"}                     │
│                                                             │
│  PUT /indexes/movies/settings                    │   │
│  {                                                          │
│    "searchableAttributes": ["title", "overview", "genres"], │
│    "filterableAttributes": ["release_date", "rating",       │
│                             "genres"],                       │
│    "sortableAttributes": ["rating", "release_date"],        │
│    "rankingRules": ["words","typo","proximity",            │
│                     "rating:desc","release_date:desc",     │
│                     "exactness"]                            │
│  }                                                          │
│                                                             │
│  # 3. 添加文档                                             │
│  POST /indexes/movies/documents                │   │
│  [{"id":1,"title":"Inception","overview":"A thief...",    │
│    "genres":["Sci-Fi","Thriller"],"rating":8.8}]           │
│                                                             │
│  # 4. 搜索                                                 │
│  POST /indexes/movies/search                   │   │
│  {                                                          │
│    "q": "incepction sci-fi",     // 故意拼错 "inception"   │
│    "filter": "rating >= 7.0 AND release_date > 2010-01-01",│
│    "sort": ["rating:desc"],                                 │
│    "limit": 20                                              │
│  }                                                          │
│  // → 返回 "Inception",拼写自动纠正!                     │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

第2部分:Meilisearch vs Elasticsearch 深度对比 ​

2.1 部署复杂度 ​

┌─────────────────────────────────────────────────────────────┐
│                部署复杂度对比                                 │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Meilisearch 部署:                                         │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Docker:                                              │   │
│  │  docker run -p 7700:7700 -v $(pwd)/data:/data       │   │
│  │    getmeili/meilisearch:latest                      │   │
│  │                                                      │   │
│  │  就这么一行。没有集群概念,没有分片,没有 node。      │   │
│  │  一个进程 = 一个搜索引擎。                            │   │
│  │                                                      │   │
│  │  HA 方案:多实例 + 应用层负载均衡 + 独立索引         │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Elasticsearch 部署:                                       │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  1. 配置 JVM Heap(-Xms31g -Xmx31g)                │   │
│  │  2. 配置 elasticsearch.yml(cluster.name, node.name,│   │
│  │     discovery.seed_hosts, network.host, ...)        │   │
│  │  3. 配置系统参数(vm.max_map_count, 文件描述符,     │   │
│  │     swap 禁用, ...)                                 │   │
│  │  4. 安装分词器插件(ik, pinyin...)                  │   │
│  │  5. 配置 TLS/认证(7.x+ 内置安全功能)               │   │
│  │  6. 配置 Kibana (可选)                               │   │
│  │  7. 3 个节点 × 以上步骤                               │   │
│  │                                                      │   │
│  │  至少半个工作日。                                     │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

2.2 功能对比矩阵 ​

┌─────────────────────────────────────────────────────────────┐
│                Meilisearch vs ES 功能深度对比                 │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  功能                        Meilisearch        ES          │
│  ────────────────────────────────────────────────────────  │
│  全文搜索                    ✅ 优秀            ✅ 优秀     │
│  即时搜索/前缀匹配           ✅ 开箱即用        ⚠️ 需配置   │
│  拼写纠错                     ✅ 默认开启        ⚠️ fuzzy   │
│  同义词管理                   ✅ REST API       ✅ API/文件  │
│  自定义排序规则               ✅ 内置引擎        ✅ 灵活     │
│  多语言支持                   ✅ 内置多语言     ⚠️ 需插件   │
│  Facet / Filter               ✅ 简单          ✅ 强大      │
│  Aggregations                 ⚠️ 仅 facet      ✅ 极强      │
│  地理位置搜索                 ✅ 内置          ✅ 内置      │
│  向量搜索 / kNN              ❌ 实验性         ✅ 成熟      │
│  SQL 查询                     ❌                ✅          │
│  数据分析/Aggregation Pipeline ❌               ✅          │
│  Logstash/Beats 集成          ❌                ✅          │
│  Kibana 可视化                ❌                ✅          │
│  集群/分片/副本               ❌ (单进程)       ✅          │
│  RBAC/多租户                  ⚠️ 基础          ✅ 企业级   │
│  Snapshot/Restore             ⚠️ Dump 文件     ✅ 增量快照 │
│  Script / Painless            ❌                ✅          │
│  Ingest Pipeline              ❌                ✅          │
│  Index Lifecycle Management   ❌                ✅          │
│  Rollover / Rollup            ❌                ✅          │
│                                                             │
│  一句话总结:                                               │
│  Meilisearch = 搜索体验的最佳化                             │
│  ES = 数据平台的全能化                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

2.3 性能特征 ​

┌─────────────────────────────────────────────────────────────┐
│                    性能特征对比                               │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  维度                Meilisearch         ES                │
│  ────────────────────────────────────────────────────────  │
│  搜索延迟 (P50)     <10ms               <50ms             │
│  搜索延迟 (P99)     <50ms               <200ms            │
│  写入吞吐           中等 (~5k/s)        高 (~50k/s 集群)  │
│  数据容量上限       数十GB-数百GB       TB-PB 级          │
│  内存占用 (空载)    ~100MB              ~1GB (JVM基础)    │
│  启动时间           秒级                十秒-分钟级         │
│  并发查询           单进程(可横向扩展) 集群原生支持       │
│                                                             │
│  延迟更低的秘密:                                           │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  Meilisearch:                                        │   │
│  │  • Rust 编写(零 GC、内存安全、SIMD 优化)          │   │
│  │  • LMDB (Memory-Mapped DB) 作为存储引擎             │   │
│  │  • 所有索引数据内存映射,无 JVM 开销                │   │
│  │                                                     │   │
│  │  ES:                                                 │   │
│  │  • JVM + Lucene(功能丰富但开销更大)               │   │
│  │  • 分布式架构带来额外的网络开销                     │   │
│  │  • GC 停顿可能导致 P99 延迟抖动                     │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

第3部分:Typesense ​

3.1 Typesense 概览 ​

┌─────────────────────────────────────────────────────────────┐
│                    Typesense 定位                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Typesense 是 Meilisearch 最接近的竞争对手,同样定位于       │
│  "轻量、快速、开箱即用的即时搜索引擎"。                     │
│                                                             │
│  核心差异:                                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                    Typesense          Meilisearch     │   │
│  │  ────────────────────────────────────────────────    │   │
│  │  编写语言     C++                   Rust             │   │
│  │  许可证       GPLv3                 MIT              │   │
│  │  集群支持     原生支持              ❌ (单进程)       │   │
│  │  API          类 ES (类似)         自研 REST API     │   │
│  │  自定义排序   排序规则              Ranking Rules    │   │
│  │  联合搜索     ✅ (Multi-Search)    ❌                │   │
│  │  向量搜索     ❌ (实验性)          ❌ (实验性)       │   │
│  │  Cloud 服务   有 (Typesense Cloud) 有 (Meili Cloud)  │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Typesense 的优势:                                         │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  1. 原生集群支持(Raft 共识协议)                    │   │
│  │     → 高可用不需要外部负载均衡器                     │   │
│  │                                                      │   │
│  │  2. C++ 编写,性能接近裸金属                         │   │
│  │     → 单节点可处理 100+ 并发搜索                     │   │
│  │                                                      │   │
│  │  3. Class ES-like API                                │   │
│  │     → 从 ES 迁移的学习成本低                         │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

3.2 Typesense 搜索实战 ​

┌─────────────────────────────────────────────────────────────┐
│                Typesense 搜索示例                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  # 创建 Collection (类比 ES Index)                          │
│  POST /collections                                         │
│  {                                                          │
│    "name": "products",                                     │
│    "fields": [                                             │
│      {"name": "title", "type": "string"},                  │
│      {"name": "price", "type": "float", "facet": true},   │
│      {"name": "brand", "type": "string", "facet": true},   │
│      {"name": "rating", "type": "int32"}                   │
│    ],                                                       │
│    "default_sorting_field": "rating"                        │
│  }                                                          │
│                                                             │
│  # 搜索                                                     │
│  GET /collections/products/documents/search               │
│    ?q=小米手机                                             │
│    &query_by=title,description                             │
│    &filter_by=price:<5000 && brand:=[小米,华为]             │
│    &sort_by=rating:desc                                    │
│    &facet_by=brand,price                                   │
│    &num_typos=2               // 允许 2 个拼写错误         │
│    &prefix=true               // 前缀匹配                  │
│                                                             │
│  # 响应                                                     │
│  {                                                          │
│    "found": 150,                                           │
│    "facet_counts": [                                       │
│      {"field_name": "brand",                               │
│       "counts": [{"value":"小米","count":80},              │
│                   {"value":"华为","count":70}]}            │
│    ],                                                       │
│    "hits": [...]                                           │
│  }                                                          │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

3.3 Typesense 集群架构 ​

┌─────────────────────────────────────────────────────────────┐
│                Typesense 集群拓扑                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  Typesense 使用 Raft 共识协议实现原生集群,无需外部 ZooKeeper│
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │              Typesense Cluster                       │   │
│  │                                                     │   │
│  │  ┌──────────────┐  ┌──────────────┐  ┌───────────┐ │   │
│  │  │   Node 1     │  │   Node 2     │  │  Node 3   │ │   │
│  │  │  (Raft       │  │  (Raft       │  │  (Raft     │ │   │
│  │  │   Leader)    │  │   Follower)  │  │   Follower)│ │   │
│  │  │  ┌────────┐  │  │  ┌────────┐  │  │ ┌───────┐ │ │   │
│  │  │  │Data    │  │  │  │Data    │  │  │ │Data   │ │ │   │
│  │  │  │Node 0  │  │  │  │Node 1  │  │  │ │Node 2 │ │ │   │
│  │  │  └────────┘  │  │  └────────┘  │  │ └───────┘ │ │   │
│  │  └──────────────┘  └──────────────┘  └───────────┘ │   │
│  │                                                     │   │
│  │  写请求 → 总是发到 Raft Leader                      │   │
│  │  读请求 → 可发到任意节点(最终一致性)               │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  Typesense 的节点既是搜索节点又是数据分片,                │
│  比 ES 的架构简单得多(不需要区分 Master/Data/Coordinating)│
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

第4部分:OpenSearch ​

4.1 OpenSearch 的由来 ​

┌─────────────────────────────────────────────────────────────┐
│                Elasticsearch → OpenSearch 分支史             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  时间线:                                                   │
│  ┌─────────────────────────────────────────────────────┐   │
│  │                                                      │   │
│  │  2010: Elasticsearch 诞生 (Shay Banon)              │   │
│  │  2012: Elastic 公司成立                              │   │
│  │  2018: ES 默认发行版中加入 X-Pack (部分收费)        │   │
│  │  2021.01: ES 7.11 → License 从 Apache 2.0 改为     │   │
│  │           SSPL + Elastic License (非 OSI 开源)      │   │
│  │           → AWS 认为这违反了开源精神               │   │
│  │                                                      │   │
│  │  2021.01: AWS Fork ES 7.10.2 → OpenSearch 1.0       │   │
│  │           + OpenSearch Dashboards (Fork Kibana)     │   │
│  │           许可证:Apache 2.0                         │   │
│  │                                                      │   │
│  │  2024: OpenSearch 2.x+ 支持向量搜索、ML插件         │   │
│  │         ES 8.x+ 同样支持,但两个项目已明显分化       │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  当前状态:ES 和 OpenSearch 是两个独立竞争的项目,          │
│  API 基本兼容但功能方向已分化。                              │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

4.2 OpenSearch vs ES 功能对比 ​

┌─────────────────────────────────────────────────────────────┐
│                OpenSearch vs ES 核心差异                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  维度               OpenSearch           ES          │   │
│  │  ───────────────────────────────────────────────     │   │
│  │  许可证             Apache 2.0          SSPL/EL     │   │
│  │  AWS 集成           ✅ 原生             ⚠️ 需配置   │   │
│  │  安全功能           免费内置           免费基础版    │   │
│  │  (RBAC/LDAP/SAML)                     高级功能收费  │   │
│  │  Alerting/通知     ✅ 免费             ✅ 收费      │   │
│  │  Anomaly Detection ✅ 免费 (ML)       ✅ 收费       │   │
│  │  SQL 支持          ✅ 内置             ✅ 内置       │   │
│  │  向量搜索           ✅ 2.x+            ✅ 8.x+       │   │
│  │  kNN 算法           FAISS / NMSLIB    Lucene HNSW  │   │
│  │  可观测性插件       独立项目           收费/基础      │   │
│  │  社区支持           AWS + 社区         Elastic 公司  │   │
│  │  版本更新速度       快 (AWS 驱动)     快 (Elastic)  │   │
│  │  与 Kibana 兼容     ❌(用 Dashboards) ✅          │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  选 OpenSearch 的理由:                                     │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  1. 合规要求:Apache 2.0 许可,无法律风险            │   │
│  │  2. AWS 生态:CloudFormation, IAM, VPC 深度集成     │   │
│  │  3. 成本:安全+告警+异常检测全部免费                 │   │
│  │  4. 不信任 Elastic 的许可变更历史                    │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  选 ES 的理由:                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  1. 更大的社区和生态(Kibana, Logstash, Beats)     │   │
│  │  2. 更成熟的功能和更多的文档/教程                    │   │
│  │  3. Elastic Cloud 托管服务体验更好                   │   │
│  │  4. 创新速度更快(Elastic 公司有全职工程师)         │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

第5部分:PostgreSQL 全文搜索 ​

5.1 何时该用 PG 全文搜索 ​

┌─────────────────────────────────────────────────────────────┐
│              PostgreSQL 全文搜索适用场景                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  场景特征:                                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  ✅ 数据已经在 PostgreSQL 中                          │   │
│  │  ✅ 搜索是辅助功能(不是核心产品)                    │   │
│  │  ✅ 数据量 < 100 万条                                 │   │
│  │  ✅ 不需要聚合分析                                    │   │
│  │  ✅ 不需要即时搜索/拼写纠错                           │   │
│  │  ✅ 团队没有运维 ES 的人                              │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  场景特征反面:                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  ❌ 搜索是核心功能(如电商搜索)                       │   │
│  │  ❌ 数据量 > 百万级                                    │   │
│  │  ❌ 需要 Facet/聚合分析                               │   │
│  │  ❌ 需要高并发(PG 全文搜索无分布式能力)             │   │
│  │  ❌ 需要拼音搜索、拼写纠错、同义词等高级功能          │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

5.2 PG 全文搜索核心语法 ​

┌─────────────────────────────────────────────────────────────┐
│              PostgreSQL 全文搜索实战                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  核心类型:                                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  tsvector: 分词后的文档(类似 ES 的倒排索引)        │   │
│  │  tsquery:  分词后的查询(类似 ES 的查询 AST)        │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  基础用法:                                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  -- 将文本转为 tsvector                               │   │
│  │  SELECT to_tsvector('english',                       │   │
│  │    'The quick brown fox jumps');                     │   │
│  │  → 'brown':3 'fox':4 'jump':5 'quick':2             │   │
│  │  (去掉了停用词 'the', 'jumps' 词干化为 'jump')       │   │
│  │                                                      │   │
│  │  -- 将查询转为 tsquery                                │   │
│  │  SELECT to_tsquery('english', 'jumping & fox');      │   │
│  │  → 'jump' & 'fox'                                   │   │
│  │                                                      │   │
│  │  -- 搜索                                              │   │
│  │  SELECT * FROM documents                             │   │
│  │  WHERE tsv_content @@ to_tsquery('english',          │   │
│  │                                  'jumping & fox');   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  生产级方案:GIN 索引 + 生成列                              │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  -- 添加 tsvector 生成列                              │   │
│  │  ALTER TABLE products ADD COLUMN tsv tsvector        │   │
│  │    GENERATED ALWAYS AS (                              │   │
│  │      setweight(to_tsvector('simple',                 │   │
│  │                   coalesce(title,'')), 'A') ||       │   │
│  │      setweight(to_tsvector('simple',                 │   │
│  │                   coalesce(description,'')), 'B')    │   │
│  │    ) STORED;                                          │   │
│  │                                                      │   │
│  │  -- 创建 GIN 索引                                    │   │
│  │  CREATE INDEX idx_products_tsv                       │   │
│  │    ON products USING GIN (tsv);                      │   │
│  │                                                      │   │
│  │  -- setweight: 'A' 权重 > 'B' 权重                   │   │
│  │  -- 意味着标题匹配比描述匹配更重要                    │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  查询语法速查:                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  'A & B'  → AND(两个词都必须有)                    │   │
│  │  'A | B'  → OR                                    │   │
│  │  '!A'     → NOT                                    │   │
│  │  'A <-> B'→ FOLLOWED BY(A 紧接着 B)              │   │
│  │  'A <2> B'→ 距离不超过 2 个位置                     │   │
│  │  'A:*'    → 前缀匹配                                │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

5.3 PG 全文搜索的局限性 ​

┌─────────────────────────────────────────────────────────────┐
│              PG 全文搜索与专用搜索引擎的差距                  │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  1. 没有倒排索引的跳表/BitSet 缓存                   │   │
│  │     → 复杂多词查询性能不如 Lucene                    │   │
│  │                                                      │   │
│  │  2. 没有 field data cache                             │   │
│  │     → 排序和聚合依赖 B-Tree,而不是列式缓存          │   │
│  │                                                      │   │
│  │  3. 没有 BM25(PG 使用 tf-idf 变体)                │   │
│  │     → 相关性排序质量稍逊                             │   │
│  │     → PG 11+ 支持 ts_rank_cd(覆盖密度排序)        │   │
│  │                                                      │   │
│  │  4. 没有分布式能力                                    │   │
│  │     → 单机处理,数据量受限于单机资源                  │   │
│  │     → 没有分片、副本、负载均衡                        │   │
│  │                                                      │   │
│  │  5. 缺少用户体验功能                                   │   │
│  │     → 无拼写纠错、无同义词引擎、无自动补全           │   │
│  │     → 需要应用层自己实现(pg_trgm 可部分弥补)       │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  但仍然是一个不错的选择,如果:                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  • 搜索不是核心功能                                    │   │
│  │  • 数据量可控(百万以内)                              │   │
│  │  • 不想引入新的基础设施                                │   │
│  │  • 只需要基本的全文检索                                │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

第6部分:选型决策树 ​

6.1 搜索引擎选型决策流程 ​

┌─────────────────────────────────────────────────────────────┐
│                    搜索引擎选型决策树                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  你的数据量多大?                                           │
│  ├── < 100 万条,且数据已在 PG 中                           │
│  │   ├── 需要 Facet/聚合?                                 │
│  │   │   ├── 需要 → ES / OpenSearch                       │
│  │   │   └── 不需要 → PostgreSQL 全文搜索 👍              │
│  │   └── 需要自动补全/纠错?                               │
│  │       ├── 需要 → Meilisearch / Typesense 👍            │
│  │       └── 不需要 → PostgreSQL 全文搜索 👍              │
│  │                                                         │
│  ├── 100 万 - 1000 万条                                    │
│  │   ├── 搜索是核心功能?                                   │
│  │   │   ├── 是 → ES / OpenSearch                         │
│  │   │   └── 否 → Meilisearch / Typesense 👍              │
│  │   ├── 需要日志分析 (ELK Stack)?                        │
│  │   │   └── 是 → ES(别无选择)                          │
│  │   └── 需要向量搜索 (RAG)?                              │
│  │       └── 是 → ES / OpenSearch                         │
│  │                                                         │
│  └── > 1000 万条                                           │
│      ├── AWS 云环境?→ OpenSearch 👍                      │
│      ├── 许可证敏感?→ OpenSearch 👍                      │
│      └── 其他 → ES                                        │
│                                                             │
│  额外维度:                                                 │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  运维能力:                                           │   │
│  │  • 1 人团队 → Meilisearch / PG                       │   │
│  │  • 有 DevOps → Typesense / ES / OpenSearch           │   │
│  │  • 有专职 SRE → ES / OpenSearch (发挥全部潜力)       │   │
│  │                                                      │   │
│  │  预算:                                               │   │
│  │  • $0 → Meilisearch / PG / OpenSearch               │   │
│  │  • 有预算 → ES Cloud / Typesense Cloud               │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40

6.2 决策优先级排序 ​

┌─────────────────────────────────────────────────────────────┐
│                    选型决策优先级                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  第1优先级:功能需求(缺了没法用)                           │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  • 需要聚合分析?→ 排除 Meilisearch / Typesense      │   │
│  │  • 需要日志分析?→ 只能用 ES                          │   │
│  │  • 需要向量搜索?→ 排除 Meilisearch / Typesense      │   │
│  │  • 需要 SQL 查询?→ 排除 Meilisearch / Typesense     │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  第2优先级:运维约束(用不了也没办法)                     │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  • 运维人员 ≤ 1 人?→ Meilisearch / PG              │   │
│  │  • 必须 Apache 2.0?→ OpenSearch / Meilisearch      │   │
│  │  • 数据安全是软性需求?→ Meilisearch / Typesense    │   │
│  │  • 数据安全是硬性需求?→ ES / OpenSearch            │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  第3优先级:体验与生态(锦上添花)                         │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  • 中文支持开箱即用?→ Meilisearch / Typesense       │   │
│  │  • 前端 SDK 丰富?→ Meilisearch (instant-meilisearch)│   │
│  │  • 社区生态成熟?→ ES                                │   │
│  │  • 托管服务便宜?→ Typesense Cloud                   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

6.3 迁移成本矩阵 ​

┌─────────────────────────────────────────────────────────────┐
│                    从不同方案迁移的代价                       │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  从 A → B 的迁移成本估算:                                 │
│                                                             │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  迁出 \ 迁入    ES       OpenSearch  Meili   Typesense│
│  │  ─────────────────────────────────────────────────   │   │
│  │  PG 全文搜索     中 (重建) 中 (重建)   低 (API) 低   │   │
│  │  ES (自建)       -         低 (兼容)   高 (重写) 高 │   │
│  │  OpenSearch      低 (兼容) -          高 (重写) 高  │   │
│  │  Meilisearch     高 (重写) 高 (重写)   -        中   │   │
│  │  Typesense       高 (重写) 高 (重写)   中        -   │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
│  从 PostgreSQL 迁出到专用搜索引擎是最常见的升级路径:       │
│  ┌─────────────────────────────────────────────────────┐   │
│  │  1. 设计新引擎的 Mapping / Schema                    │   │
│  │  2. 编写数据同步脚本 (PG → 搜索引擎)                 │   │
│  │  3. 并行运行:应用同时查 PG 和新引擎                  │   │
│  │  4. A/B 测试:对比搜索结果质量                        │   │
│  │  5. 灰度切流:10% → 50% → 100%                       │   │
│  │  6. 下线 PG 搜索(保留 PG 作主数据库)               │   │
│  └─────────────────────────────────────────────────────┘   │
│                                                             │
└─────────────────────────────────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

核心总结 ​

总结1:四大引擎定位口诀 ​

ES:          功能最多、运维最重、选它最多
OpenSearch:  ES 的开源替代品(Apache 2.0)、AWS 原生
Meilisearch: 搜索体验最好、部署最简单、集群缺失
Typesense:   轻量+集群、Meilisearch 最强竞品
PG 全文搜索: 最简单、数据在哪搜哪、百万级适用
1
2
3
4
5

总结2:选型速查 ​

条件首选备选
电商搜索(聚合+排序)ESOpenSearch
日志分析 (ELK)ES-
文档/内容站内搜索MeilisearchTypesense
SaaS 内置搜索TypesenseMeilisearch
小项目(已有 PG)PG 全文搜索Meilisearch
合规 (Apache 2.0)OpenSearchMeilisearch
RAG 向量搜索ES / OpenSearch-

总结3:三个决策问题,找到你的引擎 ​

Q1: 是否需要聚合/分析?
    Yes → ES / OpenSearch
    No  → Q2

Q2: 是否需要集群/分布式?
    Yes → Typesense / ES / OpenSearch
    No  → Q3

Q3: 追求开发体验还是功能深度?
    体验 → Meilisearch
    深度 → ES / OpenSearch
1
2
3
4
5
6
7
8
9
10
11

总结4:PG 全文搜索的边界 ​

优势:零额外运维、数据一致性天然保证、GIN 索引高效
劣势:无分布式能力、无高级搜索功能(拼写纠错、同义词引擎)
边界:百万级数据、搜索非核心功能
1
2
3

章节测试 ​

测试1:Meilisearch ​

Meilisearch 的即时搜索(Search-as-you-type)依赖哪些内置机制?如果要用 ES 实现同样的效果,需要配置哪些东西?

测试2:性能差异 ​

为什么 Meilisearch 的搜索延迟通常低于 ES?从技术栈角度解释。

测试3:集群 ​

Typesense 和 Meilisearch 在集群支持上的核心差异是什么?这如何影响生产环境部署?

测试4:OpenSearch ​

如果公司要求所有服务器软件必须是 Apache 2.0 许可,你会选择 ES 还是 OpenSearch?为什么?

测试5:PG 全文搜索 ​

PostgreSQL 的 tsvector + GIN 索引方案,在什么数据量级下性能会明显下降?为什么?

测试6:选型 ​

你是初创公司唯一的后端工程师。产品需要给一个文档管理 SaaS 添加搜索功能,数据量预计 50 万文档。你会选什么方案?说明理由。

测试7:综合 ​

一个中型电商团队(5 名后端,有 DevOps),搜索数据 500 万商品,需要:关键词搜索、品牌/价格 Facet、按销量排序、自动补全。预算充足。请给出搜索引擎选型和关键架构设计。


参考答案 ​

测试1答案 ​

答案: Meilisearch 内置:Typo Tolerance(容错匹配)、Prefix Search(前缀匹配)、分词匹配、Ranking Rules(排序规则优先级)。这些都是默认开启的,不需要配置。

ES 实现同样效果需要:

  1. 配置 edge_ngram 或 completion suggester(前缀匹配)
  2. 使用 fuzzy query(拼写纠错)
  3. 配置 multi_match + boosting(字段权重)
  4. 使用 function_score(排序规则)
  5. 自行实现搜索 UX 的 debounce 和结果更新逻辑

测试2答案 ​

答案:

  • Meilisearch 用 Rust 编写,零垃圾回收,无 GC 停顿;ES 在 JVM 上运行,GC 会导致 P99 延迟抖动
  • Meilisearch 使用 LMDB(Memory-Mapped DB),数据直接映射到虚拟内存,OS 管理缓存;ES 通过 JVM Heap + OS Page Cache 两层
  • Meilisearch 是单进程架构,无网络往返开销;ES 需要协调节点聚合各分片结果

测试3答案 ​

答案: Typesense 原生支持集群(基于 Raft 共识协议),多节点组成一个有 Leader/Follower 关系的集群,自带高可用和故障切换。

Meilisearch 是单进程架构,没有集群概念。高可用需要外部方案:多个 Meilisearch 实例 + 应用层负载均衡 + 各实例独立维护索引(数据一致性由应用层保证)。

影响:生产环境中,Typesense 可以直接以 3 节点集群部署(类似 ES 的最小部署),Meilisearch 要么接受单点故障,要么自己搭建多实例负载均衡。


测试4答案 ​

答案:选择 OpenSearch。因为 ES 从 7.11 版本开始,默认发行版的许可证已从 Apache 2.0 改为 SSPL + Elastic License,两者都不是 OSI 批准的开源许可证。Apache 2.0 对商业使用几乎没有限制,而 SSPL 要求如果你将软件作为服务提供,必须开源整个相关栈的代码(对 SaaS 公司有法律风险)。OpenSearch 作为 ES 7.10.2 的 Apache 2.0 fork,功能兼容且许可证友好。


测试5答案 ​

答案:一般在百万级(百万到几百万条)文档时,PG 全文搜索性能开始明显下降。原因:

  1. GIN 索引本身可以支持到千万级,但搜索如果涉及复杂查询(多词 AND/OR + 距离 + 排序),单机的 CPU/内存会成为瓶颈
  2. PG 缺乏专用的 field data cache 和 filter cache 机制,排序和过滤严重依赖磁盘 IO
  3. 没有分布式能力,无法利用多节点并行查询

如需突破,可以考虑:只索引必要字段、分区表 + 并行查询、读写分离、或升级为专用搜索引擎。


测试6答案 ​

答案:推荐 Meilisearch。理由:

  1. 50 万文档在单节点 Meilisearch 上表现极好
  2. 文档搜索需要即时搜索 + 拼写纠错,Meilisearch 开箱即用
  3. 唯一后端工程师 → 部署和运维成本最低(一条 Docker 命令)
  4. 不需要 Facet/聚合分析 → ES 的复杂度是多余的
  5. MIT 许可证 → SaaS 使用无法律风险

测试7答案 ​

答案:推荐 Elasticsearch。关键架构设计:

  1. 集群规模:3 Master 节点 + 5 Data 节点(每节点 4 核 32GB RAM)
  2. 分片策略:6-8 个主分片,1 个副本(每分片约 30GB)
  3. 同步方案:CDC (Canal → Kafka → ES Sink Connector),近实时同步
  4. 搜索架构:
    • 关键词搜索:multi_match (best_fields) with 字段权重
    • Facet 聚合:terms + range aggregation
    • 自动补全:completion suggester (独立字段)
    • 排序:_score + function_score (销量因子)
  5. 备选:如果团队对 AWS 有倾向,OpenSearch 也完全可以胜任

相关笔记 ​

  • [[./00-overview]] - 搜索引擎概览
  • [[./02-elasticsearch-queries]] - ES 查询 DSL 深入
  • [[./03-elasticsearch-cluster]] - ES 集群规划与运维
  • [[/03-web/06-databases-and-data-access/09-olap-databases]] - 数据分析引擎对比

下一步学习 ​

  • [ ] 实践:搭建一个 Meilisearch Docker 实例,导入自己的项目数据
  • [ ] 实践:对比同一个查询在 ES 和 Meilisearch 上的延迟差异
  • [ ] 阅读 04-ai 向量搜索与 RAG 相关内容(了解搜索的下一阶段:语义搜索与向量检索)

学习状态:🟡 开始学习

最后更新于:

Pager
上一篇4. Elasticsearch 集群规划与运维——为什么你的集群总是"黄" / Elasticsearch Cluster Planning and Operations
下一篇1. 基础设施组件全景 / Infrastructure Components Landscape

持续记录,持续成长

Copyright © Tidenflow