分片原理

由于平台接入的数据达万级,消息队列积压严重,为提高消费端 ES 的写入,中间不单纯是一些写入,做各种各样的处理,插入到第三方表,整体流程耗时非常严重,使用方不能及时搜索到商品的信息,第一期的话是全部改成批量操作,充分利用系统资源,发现这些指标还是上不去,像一些非核心的逻辑,要求不是那么实时,那我就开一个异步线程来异步化,迭代到最后面,攒批多线程插入,就先拉一批数据到全局队列中去,再开一个线程池,启动线程池,对数据进行分片后多线程批次插入,ES 提供了 Bulk API 支持批量操作,当我们有大量的写任务时,可以使用 Bulk 来进行批量写入。

当前一个数据通过路由计算公式得到的值是 shard=hash(routing)%4=0,则具体流程如下:

(1)数据写请求发送到 node1 节点,通过路由计算得到值为1,那么对应的数据会应该在主分片S1上。
(2)node1节点将请求转发到 S1 主分片所在的节点node2,node2 接受请求并写入到磁盘。
(3)并发将数据复制到三个副本分片R1上,其中通过乐观并发控制数据的冲突。一旦所有的副本分片都报告成功,则节点 node2将向node1节点报告成功,然后node1节点向客户端报告成功。

这种模式下,只要有副本在,写入延时最小也是两次单分片的写入耗时总和,效率会较低,但是这样的好处也很明显,避免写入后单个机器硬件故障导致数据丢失,在数据完整性和性能方面,一般都是优先选择数据,除非一些允许丢数据的特殊场景。

主从

一个ES集群可以有多个节点构成,一个节点就是一个ES服务实例,ES集群中节点的角色

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

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

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

节点就可以加入集群,那么ES是如何做到这一点的呢?

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

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

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

单播,当一个节点加入一个现有集群,或者组建一个新的集群时,请求发送到一台机器。当一个节点联系到单播列表中的成员时,它就会得到整个集群所有节点的状态,然后它会联系Master节点,并加入集群。

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

脑裂

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

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

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

  • 网络问题:集群间的网络延迟导致一些节点访问不到Master,认为Master 挂掉了,而master其实并没有宕机,而选举出了新的Master,并对Master上的分片和副本标红,分配新的主分片。
  • 节点负载:主节点的角色既为Master又为Data,访问量较大时可能会导致 ES 停止响应(假死状态)造成大面积延迟,此时其他节点得不到主节点的响应认为主节点挂掉了,会重新选取主节点。
  • 内存回收:主节点的角色既为Master又为Data,当Data节点上的ES进程占用的内存较大,引发JVM的大规模内存回收,造成ES进程失去响应。

如何避免脑裂:我们可以基于上述原因,做出优化措施:

  • 适当调大响应超时时间,减少误判。通过参数 discovery.zen.ping_timeout 设置节点ping超时时间,默认为 3s,可以适当调大。
  • 选举触发,我们需要在候选节点的配置文件中设置参数 discovery.zen.munimum_master_nodes 的值。这个参数表示在选举主节点时需要参与选举的候选主节点的节点数,默认值是 1,官方建议取值(master_eligibel_nodes/2)+1,其中 master_eligibel_nodes 为候选主节点的个数。这样做既能防止脑裂现象的发生,也能最大限度地提升集群的高可用性,因为只要不少于 discovery.zen.munimum_master_nodes 个候选节点存活,选举工作就能正常进行。当小于这个值的时候,无法触发选举行为,集群无法使用,不会造成分片混乱的情况。
  • 角色分离,即是上面我们提到的候选主节点和数据节点进行角色分离,这样可以减轻主节点的负担,防止主节点的假死状态发生,减少对主节点宕机的误判

image-20230822105433029

image-20230822105452064

image-20230822105547197