专栏名称: 51CTO技术栈
有趣 | 有料 | 有内涵,为您提供最优质的内容,愿我们一起悦享技术,成就人生。
目录
相关文章推荐
51好读  ›  专栏  ›  51CTO技术栈

求求你,别再问我Elasticsearch了!

51CTO技术栈  · 公众号  · 程序员  · 2020-12-10 18:05

正文

送 福 利 啦

关注 HarmonyOS技术社区 ,回复 【鸿蒙】 送10个 小米小爱音箱mini (明日开奖,赶快参与) ,还可以 免费下载 鸿蒙 入门资料


👇 扫码 立刻关注 👇

专注开源技术,共建鸿蒙生态

如今,越来越多的企业在业务场景是使用 Elasticsearch(下文统一称为 ES) 存储自己的非结构化数据。


图片来自 Pexels


例如电商业务实现商品站内搜索,数据指标分析,日志分析等,ES 作为传统关系型数据库的补充,提供了关系型数据库不具备的一些能力。


ES 最先进入大众视野的是其能够实现全文搜索的能力,也是由于基于 Lucene 的实现,内部有一种倒排索引的数据结构。


本文作者将介绍 ES 的分布式架构,以及 ES 的存储索引机制,本文不会详细介绍 ES 的 API,会从整体架构层面进行分析。


什么是倒排索引


要讲明白什么是倒排索引,首先我们先梳理下什么索引,比如一本书,书的目录页,有章节,章节名称,我们想看哪个章节,我们通过目录页,查到对应章节和页码,就能定位到具体的章节内容。


通过目录页的章节名称查到章节的页码,进而看到章节内容,这个过程就是一个索引的过程,那么什么是倒排索引呢?


比如查询《java 编程思想》这本书的文章,翻开书本可以看到目录页,记录这个章节名字和章节地址页码。


通过查询章节名字“继承”可以定位到“继承”这篇章节的具体地址,查看到文章的内容,我们可以看到文章内容中包含很多“对象”这个词。


那么如果我们要在这本书中查询所有包含有“对象”这个词的文章,那该怎么办呢?


按照现在的索引方式无疑大海捞针,假设我们有一个“对象”--→文章的映射关系,不就可以了吗?类似这样的反向建立映射关系的就叫倒排索引。


如图 1 所示,将文章进行分词后得到关键词,在根据关键词建立倒排索引,关键词构建成一个词典,词典中存放着一个个词条(关键词),每个关键词都有一个列表与其对应。

图 1

这个列表就是倒排表,存放的是章节文档编号和词频等信息,倒排列表中的每个元素就是一个倒排项。


最后可以看到,整个倒排索引就像一本新华字典,所有单词的倒排列表往往顺序地存储在磁盘的某个文件里,这个文件被称之为倒排文件。


词典和倒排文件是 Lucene 的两种基本数据结构,但是存储方式不同,词典在内存中存储,倒排文件在磁盘上。


本文不会去介绍分词,tf-idf,BM25,向量空间相似度等构建倒排索引和查询倒排索引所用到的技术,读者只需要对倒排索引有个基本的认识即可。


ES 的集群架构


集群节点


一个 ES 集群可以有多个节点构成,一个节点就是一个 ES 服务实例,通过配置集群名称 cluster.name 加入集群。


那么节点是如何通过配置相同的集群名称加入集群的呢?要搞明白这个问题,我们必须先搞清楚 ES 集群中节点的角色。


ES 中节点有角色的区分的,通过配置文件 conf/elasticsearch.yml 中配置以下配置进行角色的设定。
node.master: true/false
node.datatrue/false

集群中单个节点既可以是候选主节点也可以是数据节点,通过上面的配置可以进行两两组合形成四大分类:

  • 仅为候选主节点

  • 既是候选主节点也是数据节点

  • 仅为数据节点

  • 既不是候选主节点也不是数据节点


候选主节点: 只有是候选主节点才可以参与选举投票,也只有候选主节点可以被选举为主节点。


主节点: 负责索引的添加、删除,跟踪哪些节点是群集的一部分,对分片进行分配、收集集群中各节点的状态等,稳定的主节点对集群的健康是非常重要。


数据节点: 负责对数据的增、删、改、查、聚合等操作,数据的查询和存储都是由数据节点负责,对机器的 CPU,IO 以及内存的要求比较高,一般选择高配置的机器作为数据节点。


此外还有一种节点角色叫做协调节点,其本身不是通过设置来分配的,用户的请求可以随机发往任何一个节点,并由该节点负责分发请求、收集结果等操作,而不需要主节点转发。


这种节点可称之为协调节点,集群中的任何节点都可以充当协调节点的角色。每个节点之间都会保持联系。

图 2

发现机制


前文说到通过设置一个集群名称,节点就可以加入集群,那么 ES 是如何做到这一点的呢?


这里就要讲一讲 ES 特殊的发现机制 ZenDiscovery。


ZenDiscovery 是 ES 的内置发现机制,提供单播和多播两种发现方式,主要职责是集群中节点的发现以及选举 Master 节点。


多播也叫组播,指一个节点可以向多台机器发送请求。生产环境中 ES 不建议使用这种方式,对于一个大规模的集群,组播会产生大量不必要的通信。

单播,当一个节点加入一个现有集群,或者组建一个新的集群时,请求发送到一台机器。


当一个节点联系到单播列表中的成员时,它就会得到整个集群所有节点的状态,然后它会联系 Master 节点,并加入集群。


只有在同一台机器上运行的节点才会自动组成集群。ES 默认被配置为使用单播发现,单播列表不需要包含集群中的所有节点,它只是需要足够的节点,当一个新节点联系上其中一个并且通信就可以了。


如果你使用 Master 候选节点作为单播列表,你只要列出三个就可以了。


这个配置在 elasticsearch.yml 文件中:
discovery.zen.ping.unicast.hosts["host1", "host2:port"]

集群信息收集阶段采用了 Gossip 协议,上面配置的就相当于一个 seed nodes,Gossip 协议这里就不多做赘述了。


ES 官方建议 unicast.hosts 配置为所有的候选主节点,ZenDiscovery 会每隔 ping_interval(配置项)ping 一次。


每次超时时间是 discovery.zen.ping_timeout(配置项),3 次(ping_retries 配置项)ping 失败则认为节点宕机,宕机的情况下会触发 failover,会进行分片重分配、复制等操作。


如果宕机的节点不是 Master,则 Master 会更新集群的元信息,Master 节点将最新的集群元信息发布出去,给其他节点。


其他节点回复 Ack,Master 节点收到 discovery.zen.minimum_master_nodes 的值 -1 个候选主节点的回复,则发送 Apply 消息给其他节点,集群状态更新完毕。


如果宕机的节点是 Master,则其他的候选主节点开始 Master 节点的选举流程。


①选主


Master 的选主过程中要确保只有一个 master,ES 通过一个参数 quorum 的代表多数派阈值,保证选举出的 master 被至少 quorum 个的候选主节点认可,以此来保证只有一个 master。


选主的发起由候选主节点发起,当前候选主节点发现自己不是 master 节点,并且通过 ping 其他节点发现无法联系到主节点。


并且包括自己在内已经有超过 minimum_master_nodes 个节点无法联系到主节点,那么这个时候则发起选主。


选主流程图如下:

图 3


选主的时候按照集群节点的参数 排序。stateVersion 从大到小排序,以便选出集群元信息较新的节点作为 Master,id 从小到大排序,避免在 stateVersion 相同时发生分票无法选出 Master。


排序后第一个节点即为 Master 节点。当一个候选主节点发起一次选举时,它会按照上述排序策略选出一个它认为的 Master。

②脑裂

提到分布式系统选主,不可避免的会提到脑裂这样一个现象,什么是脑裂呢?如果集群中选举出多个 Master 节点,使得数据更新时出现不一致,这种现象称之为脑裂。

简而言之集群中不同的节点对于 Master 的选择出现了分歧,出现了多个 Master 竞争。


一般而言脑裂问题可能有以下几个原因造成:

  • 网络问题: 集群间的网络延迟导致一些节点访问不到 Master,认为 Master 挂掉了,而 master 其实并没有宕机,而选举出了新的 Master,并对 Master 上的分片和副本标红,分配新的主分片。

  • 节点负载: 主节点的角色既为 Master 又为 Data,访问量较大时可能会导致 ES 停止响应(假死状态)造成大面积延迟,此时其他节点得不到主节点的响应认为主节点挂掉了,会重新选取主节点。

  • 内存回收: 主节点的角色既为 Master 又为 Data,当 Data 节点上的 ES 进程占用的内存较大,引发 JVM 的大规模内存回收,造成 ES 进程失去响应。







请到「今天看啥」查看全文