page contents

关于分布式系统中雷同集群技术及原理,你知道多少?

写在前面在当今信息爆炸的时代,单台计算机已经无法负载日益增长的业务发展,虽然也有性能强大的超级计算机,但是这种高端机不仅费用高昂,也不灵活,一般的企业是负担不起的,而且也损失不起,...



写在前面

在当今信息爆炸的时代,单台计算机已经无法负载日益增长的业务发展,虽然也有性能强大的超级计算机,但是这种高端机不仅费用高昂,也不灵活,一般的企业是负担不起的,而且也损失不起,那么将一群廉价的普通计算机组合起来,让它们协同工作就像一台超级计算机一样地对外提供服务,就成了顺其自然的设想,但是这又增加了软件的复杂度,要求开发的软件需要具备横向扩展能力,比如:Kafka、Elasticsearch、Zookeeper等就属于这一类软件,它们天生都是"分布式的",即可以通过添加机器节点来共同地分摊数据存储和负载压力。

 

为什么需要集群?

分布在不同区域的计算机,彼此之间通过网络建立通信,相互协作作为一个整体对外提供服务,这就是集群,如果我们开发的系统具备这样的能力,那么理论上就具备无限横向扩容的能力,系统的吞吐量就会随着机器数增加而增长,那么未来当系统出现高负载的时候,就可以很好地应对这种情况。

 


为什么CAP不能同时满足?

通过上面分析,我们知道实现集群,其实就是采用多台计算机来共同承担和负载系统压力,那么就涉及到多台计算机需要参与一起处理数据,为了保证可用性,一般都会在每台计算机上备份一份数据,这样只要有一个节点保持同步状态,那么数据就不会丢失,比如kafka分区多副本、Elasticsearch的副本分片,由于同一数据块及其副本位于不用的机器,随着时间的推移,再加上不可靠的网络通信,所有机器上的数据必然会不完全一致,这个时候假如发生一种极端情况,所有的机器宕机了,又如何保证数据不丢失呢(其实只有两种方法)?

 

  • 保证可用性:选择第一台恢复正常服务的机器(不一定拥有全部数据)作为可信的数据来源,快速恢复集群,即停机时间优于同步。

  • 保证数据一致性:等待第一台拥有全部数据的机器恢复正常,再恢复集群,即同步优于停机时间,比如禁用kafka的unclean leader选举机制就是这种策略。


其实当大多数机器不可用时,就需要在可用性和一致性之间进行妥协了,所以另一个更符合分布式系统的Base理论又被创造出来了。

 

如何解决分布式存储问题?

当由多台计算机组成的集群对外提供服务时,其实就是对外提供读、写的能力。

 

1.数据块技术(data block)

为了将数据合理、均匀地写到各个机器上,提高集群写能力;为了将读请求负载均衡到不同的节点,提高集群的读能力;为了解耦数据存储和物理节点,提高分布式读写并行处理的能力,聪明的工程师引入了一个逻辑数据存储单位,统称为数据块,比如Kafka的分区(partion)、Elasticsearch的分片(shard),这样的虚拟化大大提高了集群读写的灵活性。

 

2.协调节点(coordination node)

实际上当集群作为一个整体处理数据时,可能每一个节点都会收到读写请求,但是数据又是分散在不同的节点上,所以就需要每个节点都清楚地知道集群中任意一个数据块的位置,然后再将请求转发到相应的节点,这就是“协调节点”的工作。比如:Elasticsearch的master节点管理集群范围内的所有变更,主分片管理数据块范围内的所有变更。

 

3.大多数投票机制(quorum)

百度百科:quorum,翻译法定人数,指举行会议、通过议案、进行选举或组织某种专门机构时,法律所规定的必要人数,未达法定人数无效。

 

由于网络分区的存在,这个机制被广泛地应用于分布式系统中,比如集群节点之间选举Master;数据块之间选举Header等;在分布式存储中,也被称为Quorum读写机制,即写入的时候,保证大多数节点都写入成功(一般的做法会选举一个主数据块(header),保证它写成功,然后再同步到冗余的副本数据块);读取的时候保证读取大多数节点的数据(一般的做法是由协调节点分发请求到不同的节点,然后将所有检索到的数据进行全局汇总排序后再返回);由于读写都是大多数,那么中间肯定存在最新的重叠数据,这样就能保证一定能读到最新的数据。

 

从上面分析可以得出,只要大多数节点处于活跃可用状态,那么整个集群的可用性就不会受到影响;只要大多数据块处于活跃可用的状态,那么就能持续地提供读写服务;只要有一个数据块完成了同步状态,那么数据就不会丢失;这其实就是通过一种冗余机制来尝试处理fail/recover模式的故障,通俗点讲就是容忍单点故障,至少需要部署3个节点;容忍2点故障,至少需要部署5个节点,机器节点越多分区容忍性就越强,即通过增加机器数来降低由于机器故障影响服务的概率,顿悟了吧,嘿嘿,所以保证集群可用的前提就是有奇数个节点、奇数个数据块保持活跃可用状态,不然就无法选举出master或header。

 

大多数投票机制运用起来也非常灵活,当分布式系统追求强一致性时,需要等待所有的数据快及其副本全部写入成功才算完成一次写操作,即写全部(write all),可以理解一种事务保证,要么全部写入,要么一个都不写入,比如:kafka从0.11.0.0 版本开始, 当producer发送消息到多个topic partion时,就运用了这种机制,来保证消息交付的exactly-once语义,是不是很帅,而且这种情况下,从任意一个节点都能读到最新的数据,读性能最高;当分布式系统追求最终一致性时,只需等待主数据块(leader)写入成功即可,再由主数据块通过消息可达的方式同步到副本数据块。

 

为了能够满足不同场景下对数据可靠性和系统吞吐量的要求,最大化数据持久性和系统可用性,很多组件都提供了配置项,允许用户定义这个大多数的法定数量,下面我们就来谈谈一些常用组件的配置:

 

Elasticsearch

 attachments-2020-01-y0hZYj2g5e12e75b6ee24.png

由上图可以看到,整个集群由三个运行了Elasticsearch实例的节点组成,有两个主分片,每个分片又有两个副分片,总共有6个分片拷贝,Elasticsearch内部自动将相同的分片放到了不同的节点,非常合理和理想。

当我们新建一个文档时:


  • 客户端向 Node 1 发送新建文档的写请求。

  • 节点使用文档的 _id 确定文档属于分片 0 。请求会被转发到 Node 3,因为分片 0 的主分片目前被分配在 Node 3 上。

  • Node 3 在主分片上面执行请求。如果成功了,它将请求并行转发到 Node 1 和 Node 2 的副本分片上。一旦所有的副本分片都报告成功, Node 3 将向协调节点报告成功,协调节点向客户端报告成功。


这就是Elasticsearch处理写请求的典型步骤顺序,同时每种业务场景对数据可靠性的要求和系统性能也不一样,所以Elasticsearch提供了Consistence配置项:


  • one:主分片处于活跃可用状态就可以处理写请求。

    系统吞吐量最高,但数据可能会丢失,对数据可靠性要求不是很高的场景非常适合,比如实时的时序数据处理(日志)。

  • all:主分片和所有副本分片处于活跃可用状态才允许处理写请求。

    系统吞吐量最低,但数据不会丢失。处理关键的业务数据非常合适。

  • quorum:必须有大多数的分片拷贝处于活跃可用状态才允许处理写请求。

    平衡系统吞吐量和数据可靠性,一般业务系统都使用这个配置。


Kafka

当向Kafka 写数据时,producers可以通过设置ack来自定义数据可靠性的级别:

 

  • 0:不等待broker返回确认消息。

  • 1: leader保存成功返回。

  • -1(all): 所有备份都保存成功返回。

 

备注:默认情况下,为了保证分区的最大可用性,当acks=all时,只要ISR集合中的副本分区写入成功,kafka就会返回消息写入成功。如果要真正地保证写全部(write all),那么我们需要更改配置transaction.state.log.min.isr来指定topic最小的ISR集合大小,即设置ISR集合长度等于topic的分区数。

 

如果所有的节点都挂掉,还有Unclean leader选举机制的保证,建议大家下去阅读kafka《官方指南》设计部分,深入理解kafka是如何通过引入ISR集合来变通大多数投票机制,从而更好地保证消息交付的不同语义。

 

什么是集群脑裂?

对于分布式系统,自动处理故障的关键就是能够精准地知道节点的存活状态(alive)。有时候,节点不可用,不一定就是其本身挂掉了,极有可能是暂时的网络故障;在这种情况下,如果马上选举一个master节点,那么等到网络通信恢复正常的时候,岂不是同时存在两个master,这种现象被形象地称为“集群脑裂”,先留给大家下去思考吧。呵呵,明天要早起,碎觉了,大家晚安。

 

备注:设计一个正在高可用的分布式系统,需要考虑的故障情况往往会很复杂,大多数组件都只是处理了fail/recover模式的故障,即容忍一部分节点不可用,然后等待恢复;并没有处理拜占庭故障(Byzantine),即节点间的信任问题,也许区块链可以解决吧,大家可以下去多多研究,然后我们一起讨论,共同学习,一起进步。

 

补充:大多数投票机制的优缺点


优点

大多数投票机制延迟取决于最快的服务器,即等待数据备份完成的等待时间取决于最快的follower,比如副本因子是3,header占据1位,再有1位最快的follower同步完成,就满足大多数了。

 

缺点

大多数(n+1)的节点挂掉就无法选举leader,从而整个集群彻底失去可用性,比如:为了冗余单点故障,通常需要三个节点备份数据,但是当其中两台挂掉时,整个集群就挂了。仅仅靠冗余数据来避免单点故障是不够,通常对磁盘空间需求量为2n+1倍,相应地也会导致写吞吐量下降2n+1倍,这种高昂的存储方式并不适合存储原始数据,这就是为什么quorum算法更适合共享集群配置数据,如zookeeper,这也是kafka为什么要引入一个同步状态备份集合(ISR),通过降低所需的备份数据而带来额外的吞吐量和磁盘空间,从而提高kafka处理海量实时数据的能力。


  • 发表于 2020-01-06 15:52
  • 阅读 ( 614 )

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
Pack
Pack

1135 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1470 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章