1.5.2 in-sync replica set(ISR)
Last updated
Last updated
在介绍ISR之前,我们不妨先来明确一下之前提到的两类节点:
Leader : 对外提供服务(Producer & Consumer Group)
Follower:仅从Leader处拉取数据确保同步
简单来说,Kafka把一个分区的所有副本分为了两种类型:Leader和follower,对生产者和消费者而言,它们所接触到的只有Leader节点,即不管是发送消息(message)还是拉取消息,所面对的对象都是Leader节点。
而对于follower节点而言,它们要干的事只有一个:从Leader节点处拉取消息,并保证自己和Leader是同步的。
在这种情况下,消息的更新和修改不再是单点上的简单更新,而是可以被看成“Leader更新 + follower同步” ,原先应用在单点上的确认机制显然不再有效:毕竟我们现在有多个节点需要确认。那么又该如何界定“消息成功写入”这一操作呢?另一个关键点是,如果Leader节点宕机掉,又该如何利用之前维护好的follower节点进行故障转移?
ISR的使用很好地解决了这些问题,由此引入我们对ISR的介绍。
正如我们之前所说,我们急需一个新的“协议”来界定这种多节点上的更新成功操作,Quorum和ISR就是两个这样地约定方法。
Quorum:当一个更新操作在N个节点中的W个节点上更新成功,称之为“成功提交的更新操作”
此处的W应该是一个可以自行定义的值,而“提交”这一概念按我的理解应该近似体系结构中的“commit”。就这种方法而言,一个显著的缺点是它的W值是静态的,假如节点集群中的大部分节点挂掉,以至于存活节点数小于W,那么这种约定将使得其永远无法完成一次更新。
与之相比,ISR提供了一种更为动态的约定方法。
ISR:一个由Leader动态维护的列表,包含了所有与之同步的 Replica(包含 Leader 自己)
就使用 ISR 约定的系统而言,每次数据写入时,只有 ISR 中的所有 Replica 都复制完,Leader 才会将其置为 Commit,它才能被 Consumer 所消费,并且:
ISR 是由 Leader 动态维护的,如果 Follower “掉队”,它将被 Leader 从 ISR 中移除
如果出现Leader挂掉的情况,只有ISR中的副本才有资格被选为Leader
极限情况下,ISR可以只包含 Leader,极大提高了可容忍的宕机的 Follower 的数量 (Eg . 一个topic 有 f+1个副本,kafka 冗余 f 个节点故障而不会丢失任何已经提交的消息,此时 ISR 中只有一个节点)
所谓“掉队”,在代码(Kafka 1.1)上体现为:
这里的Lag指的是follower节点相对于Leader节点的延时,默认值为10000ms,可以预见的是,这种设计在维护一致性的同时顺带滤掉了慢速节点(slow replica),保证ISR集合中的节点质量较高。
这里还有一个小插曲:实际上在0.9x版本之前的Kafka中,判断节点掉队的依据有两条:
Cond1 : lag.max.messages : 最大延迟消息数
Cond2 : lag.time.max : 最大延时
那后来为什么 cond1 被删除了呢? 我们考虑突增流量或大批量消息(比如京东双十一),Producer 一次发送的消息数量很可能 > lag.max.messages, 这样一来,所有的 follower 都落后于 leader 太多了, 它们会从ISR 中删除,这样造成的结果就是 ISR中的节点进进出出,“all followers shuttle in and out of ISR”
(感觉非常类似 OS 写页替换算法时,设计失误导致页面来来回回被swap in/out 所产生的颠簸)
于是在后来的版本更新中,智慧的Kafka设计师将Cond1删掉了。
关于这部分的具体内容,其实已经阐述完毕了,但还有另一个值得一提的事情。在新版本的Kafka抛弃zk之后,有下面这张图:
我愿把它称之为“From ISR to Quorum”