本文已收录GitHub,更有互联网大厂面试真题,面试攻略,高效学习资料等

众所周知,新闻行列在收发两头,主要是依赖营业代码,配合请求确认的机制,来保证新闻不会丢失的。而在服务端,一样平常接纳持久化和复制的方式来保证不丢新闻。

把新闻复制到多个节点上,不仅可以解决丢新闻的问题,还可以保证新闻服务的高可用。纵然某一个节点宕机了,还可以继续使用其他节点来收发新闻。以是大部分生产系统,都会把新闻行列设置成集群模式,并开启新闻复制,来保证系统的高可用和数据可靠性。

今天就和人人聊一下,新闻复制需要解决的一些问题,以及 RocketMQ 和 Kafka 都是若何应对这些问题来实现复制的。

新闻复制面临什么问题?

我们希望新闻行列最好能兼具高性能、高可用而且还能提供数据一致性的保证。虽然许多新闻行列产物宣称三个特征全都支持,但你需要知道,这都是有前置条件的。

首先来说性能。任何的复制实现方式,数据的写入性能一定是不如单节点的。这个很好明白,由于无论接纳哪种复制实现方式,都需要数据被写入到多个节点之后再返回,性能一定是不如只写入一个节点的。

需要写入的节点数目越多,可用性和数据可靠性就越好,然则写入性能就越低,这是一个自然的矛盾。不外,复制对消费的性能影响不大,不管接纳哪种复制方式,消费新闻的时刻,都只是选择多副本中一个节点去读数据而已,这和单节点消费并没有差异。

再来说一致性,新闻行列对数据一致性的要求,既包罗了“不丢新闻”这个要求,也包罗“严酷顺序”的要求。若是要确保数据一致性,必须接纳“主 - 从”的复制方式,这个结论是有严酷的数学论证的,人人只要记着就可以了。

在“主 - 从”模式下,数据先写入到主节点上,从节点只从主节点上复制数据,若是泛起主从数据不一致的情形,必须以主节点上的数据为准。这内里需要注重一下,这内里的主节点它并不是不可变的,在许多的复制实现中,当主节点泛起问题的时刻,其他节点可以通过选举的方式,酿成主节点。只要保证,在任何一个时刻,集群的主节点数不能超过 1 个,就可以确保数据一致性。

最后说一下高可用。既然必须要接纳主从的复制方式,高可用需要解决的就是,当某个主节点宕机的时刻,尽快再选出一个主节点来接替宕机的主节点。

对照快速的实现方式是,使用一个第三方的治理服务来治理这些节点,发现某个主节点宕机的时刻,由治理服务来指定一个新的主节点。但引入治理服务会带来一系列问题,好比治理服务自己的高可用、数据一致性若何保证?

有的新闻行列选择自选举的方式,由还存活的这些节点通过投票,来选出一个新的主节点,这种投票的实现方式,它的优点是没有外部依赖,可以实现自我治理。瑕玷就是投票的实现都对照复杂,而且选举的历程是对照慢的,几秒至几十秒都有可能,在选出新的主节点前,服务一直是不可用的。

大部分复制的实现,都不会选择把新闻写入所有副本再返回确认,由于这样虽然可以保证数据一致性,然则,一旦这些副本中有任何一个副本宕机,写入就会卡死了。若是只把新闻写入到一部分副本就以为写入乐成并返回确认,就可以解决卡死的问题,而且性能也会比写所有副本好许多。

到底写入多少个副本算写入乐成呢?这又是一个异常难决议的问题。

假设我们的集群接纳“一主二从三副本”的模式,若是只要新闻写入到两个副本就算是写入乐成了,那这三个节点最多允许宕机一个节点,否则就没法提供服务了。若是说我们把要求写入的副本数目降到 1,只要新闻写入到主节点就算乐成了,那三个节点中,可以允许宕机两个节点,系统依然可以提供服务,这个可用性就更好一些。然则,有可能泛起一种情形:主节点有一部分新闻还没来得复制到任何一个从节点上,主节点就宕机了,这时刻就会丢新闻,数据一致性又没有设施保证了。

以上我讲的这些内容,还没有涉及到任何复制或者选举的方式和算法,都是最质朴,最基本的原理。你可以看出,这内里是有许多自然的矛盾,以是,现在并没有一种完善的实现方案能够兼顾高性能、高可用和一致性。

差别的新闻行列选择了差别的复制实现方式,这些实现方式都有各自的优瑕玷,在高性能、高可用和一致性方面提供的能力也是各有崎岖。接下来我们一起来看一下 RocketMQ 和Kafka 分别是若何来实现复制的。

RocketMQ若何实现复制?

RocketMQ 在 2018 年底迎来了一次重大的更新,引入 Deldger,增加了一种全新的复制方式。我们先来说一下传统的复制方式。

在 RocketMQ 中,复制的基本单位是 Broker,也就是服务端的历程。复制接纳的也是主从方式,通常情形下设置成一主一从,也可以支持一主多从。

RocketMQ 提供了两种复制方式,一种是异步复制,新闻先发送到主节点上,就返回“写入乐成”,然后新闻再异步复制到从节点上。另外一种方式是同步双写,新闻同步双写到主从节点上,主从都写乐成,才返回“写入乐成”。这两种方式本质上的区别是,写入多少个副本再返回“写入乐成”的问题,异步复制需要的副本数是 1,同步双写需要的副本数是2。

我刚刚讲过,若是在返回“写入乐成”前,需要写入的副本数不够多,那就会丢新闻。对RocketMQ 来说,若是接纳异步复制的方式会不会丢新闻呢?谜底是,并不会丢新闻。我来跟你说一下为什么不会丢新闻。

在 RocketMQ 中,Broker 的主从关系是通过设置牢固的,不支持动态切换。若是主节点宕机,生产者就不能再生产新闻了,消费者可以自动切换到从节点继续进行消费。这时刻,纵然有一些新闻没有来得及复制到从节点上,这些新闻依然躺在主节点的磁盘上,除非是主节点的磁盘坏了,否则等主节点重新恢复服务的时刻,这些新闻依然可以继续复制到从节点上,也可以继续消费,不会丢新闻,新闻的顺序也是没有问题的。

从设计上来讲,RocketMQ 的这种主从复制方式,牺牲了可用性,换取了对照好的性能和数据一致性

那 RocketMQ 又是若何解决可用性的问题的呢?一对儿主从节点可用性不行,多来几对儿主从节点不就解决了?RocketMQ 支持把一个主题漫衍到多对主从节点上去,每对主从节点中负担主题中的一部分行列,若是某个主节点宕机了,会自动切换到其他主节点上继续发新闻,这样既解决了可用性的问题,还可以通过水平扩容来提升 Topic 总体的性能。

这种复制方式在大多数场景下都可以很好的事情,但也面临一些问题。

好比,在需要保证新闻严酷顺序的场景下,由于在主题层面无法保证严酷顺序,以是必须指定行列来发送新闻,对于任何一个行列,它一定是落在一组特定的主从节点上,若是这个主节点宕机,其他的主节点是无法替换这个主节点的,否则就无法保证严酷顺序。在这种复制模式下,严酷顺序和高可用只能选择一个。

RocketMQ 引入 Dledger,使用新的复制方式,可以很好地解决这个问题。我们来看一下Dledger 是怎么来复制的。

Dledger 在写入新闻的时刻,要求至少新闻复制到半数以上的节点之后,才给客户端返回写入乐成,而且它是支持通过选举来动态切换主节点的。

同样拿 3 个节点举例说明一下。当主节点宕机的时刻,2 个从节点会通过投票选出一个新的主节点来继续提供服务,相比主从的复制模式,解决了可用性的问题。由于新闻要至少复制到 2 个节点上才会返回写入乐成,纵然主节点宕机了,也至少有一个节点上的新闻是和主节点一样的。Dledger 在选举时,总会把数据和主节点一样的从节点选为新的主节点,这样就保证了数据的一致性,既不会丢新闻,还可以保证严酷顺序。

固然,Dledger 的复制方式也不是完善的,依然存在一些不足:好比,选举历程中不能提供服务。最少需要 3 个节点才气保证数据一致性,3 节点时,只能保证 1 个节点宕机时可用,若是 2 个节点同时宕机,纵然另有 1 个节点存活也无法提供服务,资源的行使率对照低。另外,由于至少要复制到半数以上的节点才返回写入乐成,性能上也不如主从异步复制的方式快。

讲完了 RocketMQ,我们再来看看 Kafka 是怎么来实现复制的。

Kafka是若何实现复制的?

Kafka 中,复制的基本单位是分区。每个分区的几个副本之间,组成一个小的复制集群,Broker 只是这些分区副本的容器,以是 Kafka 的 Broker 是不分主从的。

分区的多个副本中也是接纳一主多从的方式。Kafka 在写入新闻的时刻,接纳的也是异步复制的方式。新闻在写入到主节点之后,并不会马上返回写入乐成,而是守候足够多的节点都复制乐成后再返回。在 Kafka 中这个“足够多”是多少呢?Kafka 的设计哲学是,让用户自己来决议。

Kafka 为这个“足够多”缔造了一个专有名词:ISR(In Sync Replicas),翻译过来就是“保持数据同步的副本”。ISR 的数目是可配的,但需要注重的是,这个 ISR 中是包罗主节点的。

Kafka 使用 ZooKeeper 来监控每个分区的多个节点,若是发现某个分区的主节点宕机了,Kafka 会行使 ZooKeeper 来选出一个新的主节点,这样解决了可用性的问题。ZooKeeper 是一个漫衍式协调服务,后面,我会专门用一节课来先容 ZooKeeper。选举的时刻,会从所有 ISR 节点中来选新的主节点,这样可以保证数据一致性。

默认情形下,若是所有的 ISR 节点都宕机了,分区就无法提供服务了。你也可以选择设置成让分区继续提供服务,这样只要有一个节点还在世,就可以提供服务,价值是无法保证数据一致性,会丢新闻。

Kafka 的这种高度可设置的复制方式,优点是异常天真,你可以通过设置这些复制参数,在可用性、性能和一致性这几方面做天真的取舍,瑕玷就是学习成本对照高。

总结

今天主要和人人分享了,新闻复制需要面临的问题以及 RocketMQ 和 Kafka 都是若何应对这些问题来实现复制的。

RocketMQ 提供新、老两种复制方式:传统的主从模式和新的基于 Dledger 的复制方式。传统的主从模式性能更好,但天真性和可用性稍差,而基于 Dledger 的复制方式,在Broker 故障的时刻可以自动选举出新节点,可用性更好,性能稍差,而且资源行使率更低一些。Kafka 提供了基于 ISR 的加倍天真可设置的复制方式,用户可以自行设置,在可用性、性能和一致性这几方面凭据系统的情形来做取舍。然则,这种天真的设置方式学习成本较高。

并没有一种完善的复制方案,可以同时能够兼顾高性能、高可用和一致性。你需要凭据你现实的营业需求,先做出取舍,然后再去设置新闻行列的复制方式。