最近女主在项目中使用到 ElasticSearch 来做索引。但是对 ElasticSearch 的一些原理还是比较模糊,所以就梳理了一下 ElasticSearch 的基本原理,分享给大家。
我们首先从 ElasticSearch 的启动过程开始,逐步了解其工作原理。
启动过程
获取集群 node 列表
在 UnicastZenPing 构造函数中,向 discovery.zen.ping.unicast.hosts 配置的节点列表发送请求,获取到 DiscoveryNode 列表。
选主流程
通过 UnicastZenPing 发送 ping,从 response 信息中找到 master,如果没有 master,进入选主流程。
启动任务
选为 master 节点后,会启动计划任务。
集群管理
集群启动后可以根据 API 接口进行管理监控。
新节点加入流程
当 ElasticSearch 的节点启动后,它会利用多播(multicast)或者单播(如果用户更改了配置)寻找集群中的其它节点,并与之建立连接。这个过程如下图所示:
New ElasticSearch Node (新节点)
新节点加入后,会通过多播 Multicast request(发出请求),寻找集群其他节点并和集群建立连接。
需要注意的是,从用户的角度来看,主节点在 ElasticSearch 中并没有占据着重要的地位,这与其它的系统(比如数据库系统)是不同的。实际上用户并不需要知道哪个节点是主节点;所有的操作需求可以分发到任意的节点,ElasticSearch 内部会完成这些让用户感到不明觉历的工作。在必要的情况下,任何节点都可以并发地把查询子句分发到其它的节点,然后合并各个节点返回的查询结果。最后返回给用户一个完整的数据集。所有的这些工作都不需要经过主节点转发(节点之间通过 P2P 的方式通信)。
探测失效节点
在正常工作时,主节点会监控所有的节点,查看各个节点是否工作正常。如果在指定的时间里面,节点无法访问,该节点就被视为出故障了,接下来错误处理程序就会启动。集群需要重新均衡——由于该节点出现故障,分配到该节点的索引分片丢失。其它节点上相应的分片就会把工作接管过来。换句话说,对于每个丢失的主分片,新的主分片将从剩余的分片副本(Replica)中选举出来。 以 3 个 Node 为例:
说明:Node1 是 master 节点,P 为 primary 主分片的缩写,R 为 replica 副本分片。
当 Node1 挂掉的时候,如下:
由于一个集群必须要有一个主节点才能使其功能正常,所以集群做的第一件事就是各节点选举了一个新的主节点:Node 2。
主分片 1 和 2 在我们杀掉 Node 1 时已经丢失,我们的索引在丢失主分片时不能正常工作。如果此时我们检查集群健康,我们将看到状态 red:不是所有主节点都可用!
幸运的是丢失的两个主分片的完整拷贝存在于其他节点上,所以新主节点做的第一件事是把这些在 Node 2 和 Node 3 上的复制分片升级为主分片,这时集群健康回到 yellow 状态。这个提升是瞬间完成的。
集群管理和监控
通过管理和监控部分的 API,用户可以更改集群的设置。比如调整节点发现机制(discovery mechanism) 或者更改索引的分片策略。用户可以查看集群状态信息,或者每个节点和索引和统计信息。
如:获取集群健康信息 GET /cluster/health 获取集群配置信息 GET /cluster/settings 下图为 chrome head 插件的集群展示结果:
可以看到集群有多少个节点,集群健康值等。
##ElasticSearch 读写原理
写操作原理
Coordinating Node
协调节点默认使用文档 ID 参与计算(也支持通过 routing),以便为路由提供合适的分片。
Shard
当分片所在的节点接收到来自协调节点的请求后,会将请求写入到 Memory Buffer,然后定时(默认是每隔 1 秒)写入到 Filesystem Cache,这个从 Momery Buffer 到 Filesystem Cache 的过程就叫做 refresh。
Memory Buffer | Filesystem Cache
当然在某些情况下,存在 Momery Buffer 和 Filesystem Cache 的数据可能会丢失,ES 是通过 translog 的机制来保证数据的可靠性的。其实现机制是接收到请求后,同时也会写入到 translog 中,当 Filesystem cache 中的数据写入到磁盘中时,才会清除掉,这个过程叫做 flush。
Transaction Log
在 flush 过程中,内存中的缓冲将被清除,内容被写入一个新段,段的 fsync 将创建一个新的提交点,并将内容刷新到磁盘,旧的 translog 将被删除并开始一个新的 translog。
flush 触发的时机是定时触发(默认 30 分钟)或者 translog 变得太大(默认为 512M)时。
读操作原理
搜索被执行成一个两阶段过程,我们称之为 Query Then Fetch;
Coordinating Node
在初始查询阶段时,查询会广播到索引中每一个分片拷贝(主分片或者副本分片)。 每个分片在本地执行搜索并构建一个匹配文档的大小为 from + size 的优先队列。PS:在搜索的时候是会查询 Filesystem Cache 的,但是有部分数据还在 Memory Buffer,所以搜索是近实时的。
Shard
每个分片返回各自优先队列中 所有文档的 ID 和排序值 给协调节点,它合并这些值到自己的优先队列中来产生一个全局排序后的结果列表。
Coordinating Node
接下来就是 取回阶段,协调节点辨别出哪些文档需要被取回并向相关的分片提交多个 GET 请求。每个分片加载并 丰富 文档,如果有需要的话,接着返回文档给协调节点。一旦所有的文档都被取回了,协调节点返回结果给客户端。
补充:Query Then Fetch 的搜索类型在文档相关性打分的时候参考的是本分片的数据,这样在文档数量较少的时候可能不够准确,DFS Query Then Fetch 增加了一个预查询的处理,询问 Term 和 Document frequency,这个评分更准确,但是性能会变差。
总结
以上主要介绍了 ES 的工作原理,ES 的魅力远不止如此,同时 ES 的开源特性也使得它社区活跃,版本迭代更新迅速,目前已经更新到 6.x 版本,如有兴趣可到 ES 官网了解最新的特性。
本文转载自公众号 360 云计算(ID:hulktalk)。
原文链接:
https://mp.weixin.qq.com/s/wjMqSbfzkmin5awHthi_5A
评论