2、ElasticSearch基础回顾:ES的分布式架构、倒排索引原理、RESTful API、文档与索引的概念、集群健康状态检查

好,咱们正式开始聊ES。说实话,很多同学一上来就急着调参数、写查询,结果出了问题根本不知道从哪排查。我个人习惯是,先把地基打牢。ES的底层原理搞懂了,后面搭建推荐系统才会顺手。

2.1 文档与索引:别把关系型数据库那套带进来

先说说最基础的概念——文档(Document)索引(Index)

ES里的文档,说白了就是一个JSON对象。它不像MySQL那样有固定的表结构,你可以在同一个索引里放不同字段的文档。我刚开始用ES时,总想着“这玩意儿得先建表吧?”——其实不用。ES是schema-less的,你直接往里扔JSON就行,它会自动推断字段类型。

举个例子,一个用户行为文档长这样:

{
  "user_id": "u12345",
  "item_id": "i67890",
  "action": "click",
  "timestamp": "2024-01-15T10:30:00Z",
  "duration": 12.5
}

索引呢,就是一堆相似文档的集合。你可以把它类比成MySQL里的“数据库”,但又不完全一样。ES的索引是分布式的,一个索引会被切分成多个分片,分散到不同节点上。

小提示: 我建议你在设计索引时,提前规划好字段类型。虽然ES能自动推断,但有时候它会猜错。比如时间戳字段,它可能当成字符串处理,导致你后面做范围查询时出问题。

2.2 倒排索引原理:ES为什么这么快?

ES的查询速度为什么这么快?核心秘密就是倒排索引

你想想看,传统的关系型数据库,比如MySQL,它存数据就像一本新华字典——按拼音顺序排好,你要查“张”字,得从第一页翻到最后一页(全表扫描),或者走B+树索引。但ES不一样,它用的是倒排索引

什么叫倒排?举个例子:

假设你有三篇文档:

  • 文档1:我喜欢吃苹果
  • 文档2:苹果很好吃
  • 文档3:我不喜欢香蕉

ES会先对每个文档做分词,然后建一张表:

词条(Term) 文档ID列表(Posting List)
[1, 3]
喜欢 [1]
[1]
苹果 [1, 2]
[2]
好吃 [2]
[3]
香蕉 [3]

当你搜索“苹果”时,ES直接去倒排索引里找这个词条,瞬间就知道它在文档1和文档2里。这就是为什么ES对全文搜索场景特别擅长。

重点: 倒排索引的核心思想是“以词找文档”,而不是“遍历文档找词”。这个思维转变很重要,后面我们做推荐系统的召回层时,也会用到类似思路。

我曾经在项目中遇到过一个问题:用户搜索“手机壳”,结果“手机壳”这个词在文档里被分词成了“手机”和“壳”,导致匹配到了很多不相关的结果。嗯,这里要注意——分词器(Analyzer)的选择直接影响搜索质量。中文场景下,我建议用IK分词器,它对中文词汇的切分更准确。

2.3 分布式架构:ES是怎么做到高可用的?

ES的分布式架构,说白了就是分片(Shard)副本(Replica)的组合。

一个索引会被拆成多个主分片(Primary Shard),每个主分片又可以有一到多个副本分片(Replica Shard)。主分片负责写操作,副本分片负责读操作,同时提供容错能力。

举个例子,假设你有一个索引,设置了3个主分片、每个主分片有1个副本。那么:

  • 数据会被均匀分布到3个主分片上
  • 每个主分片的数据会复制一份到副本分片
  • 如果某个节点挂了,ES会自动把副本分片提升为主分片

你可能会问:“主分片数量能不能改?”——不能。主分片数量在索引创建时就固定了,之后无法修改。我刚开始做ES时踩过这个坑,索引建好后发现数据量远超预期,想增加分片却不行,只能重建索引。所以,提前规划好主分片数量很重要。

避坑指南: 我曾经在生产环境中把主分片数设得太大(比如一个索引设了20个分片),结果每个分片的数据量很小,但集群管理开销巨大,查询性能反而下降了。一般建议每个分片的数据量控制在20-40GB之间。

2.4 RESTful API:用HTTP操作一切

ES的所有操作都通过RESTful API暴露出来。你不需要装什么客户端,直接用curl或者Postman就能玩起来。

常用的API有这些:

操作 HTTP方法 示例路径
创建索引 PUT /my_index
写入文档 POST /my_index/_doc
查询文档 GET /my_index/_search
删除索引 DELETE /my_index

举个例子,往索引里写一条数据:

POST /my_index/_doc
{
  "title": "推荐系统入门",
  "content": "这是一篇关于推荐系统的文章..."
}

返回结果里会有一个_id字段,那是ES自动生成的文档ID。你也可以自己指定ID:

PUT /my_index/_doc/1
{
  "title": "推荐系统入门",
  "content": "这是一篇关于推荐系统的文章..."
}
小技巧: 我个人习惯在写入数据时指定业务ID作为文档ID,比如用user_id+item_id的组合。这样后面做去重或更新时,直接按ID操作,不用再查一遍。

2.5 集群健康状态检查:别等出事了才看

最后,说说怎么检查集群的健康状态。这个操作很简单,但很多人容易忽略。

执行:

GET /_cluster/health

返回结果类似:

{
  "cluster_name": "my_cluster",
  "status": "yellow",
  "number_of_nodes": 3,
  "number_of_data_nodes": 3,
  "active_primary_shards": 10,
  "active_shards": 20,
  "relocating_shards": 0,
  "initializing_shards": 0,
  "unassigned_shards": 5
}

状态有三种:

  • green:所有主分片和副本分片都正常。这是理想状态。
  • yellow:所有主分片正常,但有些副本分片没分配。常见于单节点集群,因为副本不能和主分片在同一节点。
  • red:有主分片丢失了。这是严重问题,需要立即处理。

我记得有一次线上集群突然变成yellow状态,排查了半天,发现是磁盘空间不足,ES自动把副本分片停掉了。嗯,这里要注意——磁盘水位线设置很重要,建议提前配置好告警。

总结一下: ES的分布式架构、倒排索引、RESTful API,这三块是后续搭建推荐系统的基础。文档和索引的概念要理解透彻,集群健康状态要养成定期检查的习惯。下一章,我们会把这些知识用起来,开始构建推荐系统的数据管道。