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的索引是分布式的,一个索引会被切分成多个分片,分散到不同节点上。
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时踩过这个坑,索引建好后发现数据量远超预期,想增加分片却不行,只能重建索引。所以,提前规划好主分片数量很重要。
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": "这是一篇关于推荐系统的文章..."
}
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自动把副本分片停掉了。嗯,这里要注意——磁盘水位线设置很重要,建议提前配置好告警。