搜索引擎

搜索引擎提供数据库无法高效完成的全文搜索、近实时检索和向量检索能力。

为什么需要搜索引擎

数据库 LIKE '%关键词%':
  - 不走索引,全表扫描
  - 百万级数据时极慢
  - 不支持分词、相关度排序

Elasticsearch:
  - 倒排索引,毫秒级响应
  - 支持中文分词
  - 相关度评分(BM25)
  - 支持聚合分析
  - 支持向量检索(kNN)

Elasticsearch 架构

┌──────────────────────────────────────────┐
│            ES Cluster                    │
│                                          │
│  ┌──────────┐  ┌──────────┐  ┌────────┐ │
│  │  Node 0  │  │  Node 1  │  │ Node 2 │ │
│  │ Master   │  │  Data    │  │  Data  │ │
│  └──────────┘  └──────────┘  └────────┘ │
│                                          │
│  Index: orders                           │
│    ├── Shard 0 (Primary → Node 1)       │
│    ├── Shard 0 (Replica → Node 2)       │
│    ├── Shard 1 (Primary → Node 2)       │
│    └── Shard 1 (Replica → Node 1)       │
└──────────────────────────────────────────┘

节点角色:

角色职责
Master集群状态管理(Index 创建/删除、节点加入/离开)
Data存储数据,执行查询
Coordinating接收请求,路由到对应 Data 节点,合并结果
Ingest写入前做数据预处理(类似 ETL Pipeline)

倒排索引原理

正向索引(文档 → 词):
  Doc1: "今天 天气 很好"
  Doc2: "今天 下雨"

倒排索引(词 → 文档):
  "今天" → [Doc1, Doc2]
  "天气" → [Doc1]
  "很好" → [Doc1]
  "下雨" → [Doc2]

搜索 “今天天气” 时:

  1. 分词:[“今天”, “天气”]
  2. 查倒排索引:今天 → [Doc1,Doc2],天气 → [Doc1]
  3. 取交集或并集,按相关度排序
  4. 返回 Doc1(相关度最高)

数据写入流程(与 DB 同步)

MySQL / PostgreSQL
       │
  Binlog 变更
       │
  Canal / Debezium(CDC 工具)
       │
  Kafka(解耦,削峰)
       │
  Consumer(写入 ES)
       │
  Elasticsearch(可搜索,近实时,1s 延迟)

直连方案(低延迟,简单):

业务服务
  ├── 写 DB(事务)
  └── 写 ES(异步,允许少量延迟)

核心查询能力

全文搜索

{
  "query": {
    "match": {
      "title": "云原生 Kubernetes"
    }
  }
}

支持分词、相关度评分、Highlight 高亮。

聚合分析

{
  "aggs": {
    "sales_by_day": {
      "date_histogram": {
        "field": "created_at",
        "calendar_interval": "day"
      }
    }
  }
}

向量检索(kNN)

{
  "knn": {
    "field": "embedding",
    "query_vector": [0.1, 0.2, ...],
    "k": 10,
    "num_candidates": 100
  }
}

支持语义搜索、以图搜图、RAG 检索。

主流方案对比

方案特点适用场景
Elasticsearch生态最完善,功能全面通用搜索、日志分析
OpenSearchAWS 维护的 ES 分支,开源友好云上部署
Meilisearch轻量,毫秒级,配置简单中小型应用、前端搜索
TypesenseRust,极快,易用面向用户的搜索框
Qdrant向量专用,高性能AI / 语义检索

生产注意事项

Mapping 设计:

  • 不需要搜索的字段设为 index: false,节省空间
  • 大文本字段设为 keyword 类型时注意 256 字节限制
  • 时间字段统一使用 date 类型

性能优化:

  • 写入时批量(Bulk API),减少网络开销
  • 查询时指定字段(_source includes),减少传输
  • 避免深分页(使用 search_after 替代 from/size
  • 冷热数据分层(热数据 SSD,冷数据 HDD)

K8s 部署:

  • 使用 StatefulSet,每个 Pod 挂载独立 PVC
  • 生产环境建议使用 ECK(Elastic Cloud on Kubernetes) Operator 管理