Elasticsearch 是一个分布式、可扩展、近实时的搜索与数据分析引擎。
- 一个分布式的实时文档存储,每个字段可以被索引与搜索。
- 一个分布式实时分析搜索引擎。
- 文档数据库
为什么使用Elasticsearch
DB局限性
- 复杂条件查询能力 • 关联查询效率低 • 不具备弹性扩展能力 • 索引创建/使用复杂度 • 超大数据量
- DB解决了ACID事务
为什么选择Elasticsearch
- 查询规则不固定,数据量大,要求查询时延底
- 弹性扩展能力
- ES解决高效查询
Elasticsearch 原理
基本概念
- Master节点: 管理索引:创建索引、删除索引、分配分片, 维护元数据, 管理集群节点状态, 不负责数据写入和查询
- 协调节点(Coordinating node):负责接收客户端的请求,将请求路由到到合适的节点,并将结果汇集到一起。
- 数据节点(DataNode):一个运行的Elasticearch实例,一般是一台机器上的一个进程,比如我们在自己的机器上面起了两个Elastic,就相当于是两个节点了。
- 索引(Index):包括配置信息settings和mapping和倒排正排数据文件,一个索引的数据文件可能会分布于一台机器,也有可能分布于多台机器。
- 主分片(Primary Shard):为了支持更大量的数据,索引一般会按某个维度分成多个部分,每个部分就是一个分片,分片被节点(DataNode)管理。一个节点(DataNode)一般会管理多个分片,这些分片可能是属于同一份索引,也有可能属于不同索引,但是为了可靠性和可用性,同一个索引的分片尽量会分布在不同节点(DataNode)上,否则一个节点崩了,整个index都没法使用了。分片有两种,主分片和副本分片。主分片负责处理写入请求和存储数据。
- 副本(Replica Shard):同一个分片(Shard)的备份数据,一个分片可能会有0个或多个副本。
倒排索引
正排索引
文档编号 | 文档内容 |
---|
1 | James Ennis |
2 | James Harden |
3 | Justin James |
4 | LeBron James |
5 | James John |
经过文档索引化后:
索引 | 文档频率 | 倒排列表 |
---|
James | 5 | (1;1;<1>),(2;1;<1>),(3;1;<2>),(4;1;<2>)(5;1;<1>) |
- 不仅会记录每个分词出现的次数,还会记录这些分词在doc中的一系列信息。(1;1;<1>) 就是 在文档id为1的时候出现,出现次数为1,在第一个位置。
写入原理
- ES集群中的协调节点负责接收来自客户端的写请求,当协调节点收到请求时,ES通过文档到分片的映射算法找到对应的主分片,将请求转发给主分片处理,主分片完成写入之后,将写入同时发送给副本分片
- 副本分片执行写入操作后返回主分片
- 主分片再将结果返回给协调节点,协调节点将结果返回给客户端,完成一次完整的写入过程。
- 路由算法:shard_num=hash(_routing) % num_primary_shards
准实时索引和持久化实现: 分段存储+延迟写
- 当有新数据写入的时候,ES首先写入Index Buffer区域,此时是无法检索的。
- 默认情况下ES每秒钟进行一次Refresh操作,将Index Buffer中的index刷新到文件系统缓存,在文件系统缓存中,是以Segment进行存储的,而且是可以被搜索到的,这就是ES实现近实时搜索:按照时间频率触发,默认情况是每 1 秒触发 1 次 Refresh,可通过index.refresh_interval 设置;
- 当Index Buffer 被占满的时候,会触发 Refresh,Index Buffer 的大小默认值是 JVM 所占内存容量的 10%;
- 手动调用调用Refresh API
- Merge:减少查询次数,对小Segment进行段合并
- Flush操作是将Segment从文件系统缓存写入到磁盘进行持久化,在执行 Flush 的时候会依次执行下面操作:
- 清空Index Buffer
- 记录 Commit Point
- 刷新Segment到磁盘
- 删除translog
- Translog机制:为了保障数据安全,ES增加了Translog, 在数据写入Index Buffer的同时,写入一份到Translog。默认每个写入请求,Translog会追加写入磁盘的,这样就可以防止服务器宕机后数据丢失。
写入配置
值 | 含义 | 备注 |
---|
quorum | 大多数的分片副本状态没问题就允许执行写 | int( (primary + number_of_replicas) / 2 ) + 1,默认配置 |
one | 只要主分片状态 ok 就允许执行写 | |
all | 必须要主分片和所有副本分片的状态没问题才允许执行写 | |
- timeout
如果没有足够的副本分片会发生什么? Elasticsearch 会等待,希望更多的分片出
现。默认情况下,它最多等待 1 分钟。 如果你需要,你可以使用 timeout 参数使它更早终止
检索原理
- 协调节点(Coordinating Node)将查询请求广播到每一个数据节点,(Query 阶段)
- 数据节点的分片会处理该查询请求 每个分片进行数据查询,将符合条件的数据放在一个优先队列中,并将这些数据的文档ID、节点信息、分片信息返回给协调节点 (Query 阶段)
- 协调节点将所有的结果进行汇总,并进行全局排序 (Query 阶段)
- 协调节点向包含这些文档ID的分片发送get请求,对应的分片将文档数据返回给协调节点,最后协调节点将数据返回给客户端 (Fetch 阶段)
一个典型的ES搜索架构
服务 | 描述 | 备注 |
---|
Source data Queue | 外部团队数据变更数据源 | |
Data Proxy | 消费外部团队数据的消费程序 | |
Internal Queue | Data Proxy 消费之后的数据可以按照业务再分区写入到消息队列中 | |
Process | 处理Internal Queue的数据,请求Cache 或者查询DB,其他服务的API丰富数据 | 可以是JAVA,Go,Python代码开发 |
Cache | 缓存数据 | |
DB | 数据源 | |
Service API | 其他服务接口 | |
Internal Service | 内部服务 | |
Search API | 查询服务 | |
ES | ES搜索引擎 | 存储真正需要搜索的数据 |
Admin | 搜索服务管理端服务 | 提供给原因人员ES数据查询能力、刷新index数据、全量构建Index数据 |
Operator | 运营人员 | 运营人员使用Admin对数据进行查询更新 |
ES 使用建议
写优化
- 批量提交。Es提供了bulk api支持批量操纵,当有大量写任务的时候,可以用bulk进行大量写入。
读优化
- 避免大结果集和深翻,基本上会采取业务上做限制的方式来实现
- 使用alias访问索引,reindex 时可以做到无感切换
- 尽量使用Filter来替代query,filter 不需要做 相关性的计算(打分),filter的结果可以被缓存
文档参考
- ES 深分页问题解决方案:https://juejin.cn/post/7010660177791680520
- ElasticSearch 原理解析:https://xie.infoq.cn/article/55095e9626718380c4072f5fb
- Elasticsearch 技术分析:https://www.cnblogs.com/jajian/category/1280015.html