Kafka的可靠性保证

概念

  1. 创建Topic的时候可以指定 --replication-factor 3 ,表示分区的副本数,不要超过broker的数量。
  2. Leader是负责读写的节点,⽽其他副本则是Follower。Producer只把消息发送到Leader,Follower定期地到Leader上Pull数据。
  3. ISR是Leader负责维护的与其保持同步的Replica列表,即当前活跃的副本列表。如果⼀个Follow落后太多,Leader会将它从ISR中移除。落后太多意思是该Follow复制的消息落后于Leader的条数超过预定值(参数: replica.lag.max.messages 默认值:4000)或者Follow⻓时间没有向Leader发送fetch请求(参数: replica.lag.time.max.ms 默认值:10000)。
  4. 为了保证可靠性,可以设置 acks=all 。Follower收到消息后,会像Leader发送ACK。⼀旦Leader收到了ISR中所有Replica的ACK,Leader就commit,那么Leader就向Producer发送ACK。

副本的分配:

当某个topic的 --replication-factor 为N(N>1)时,每个Partition都有N个副本,称作replica。原则上是将replica均匀的分配到整个集群上。不仅如此,partition的分配也同样需要均匀分配,为了更好的负载均衡。
副本分配的三个⽬标:

  1. 均衡地将副本分散于各个broker上
  2. 对于某个broker上分配的分区,它的其他副本在其他broker上
  3. 如果所有的broker都有机架信息,尽量将分区的各个副本分配到不同机架上的broker。
    在不考虑机架信息的情况下:
  4. 第⼀个副本分区通过轮询的⽅式挑选⼀个broker,进⾏分配。该轮询从broker列表的随机位置进⾏轮询。
  5. 其余副本通过增加偏移进⾏分配。


    image.png

Leader的选举

如果Leader宕机了该怎么办?很容易想到我们在Follower中重新选举⼀个Leader,但是选举哪个作为leader呢?
Follower可能已经落后许多了,因此我们要选择的是”最新”的Follow:新的Leader必须拥有与原来Leader commit过的所有信息。
kafka动态维护⼀组同步leader数据的副本(ISR),只有这个组的成员才有资格当选leader,kafka副本写⼊不被认为是已提交,直到所有的同步副本已经接收才认为。这组ISR保存在zookeeper,正因为如此,在ISR中的任何副本都有资格当选leader。
基于Zookeeper的选举⽅式
⼤数据很多组件都有Leader选举的概念,如HBASE等。它们⼤都基于ZK进⾏选举,所有Follow都在ZK上⾯注册⼀个Watch,⼀旦Leader宕机,Leader对于的Znode会⾃动删除,那些Follow由于在Leader节点上注册了Watcher,故可以得到通知,就去参与下⼀轮选举,尝试去创建该节点,zK会保证只有⼀个Follow创建成功,成为新的Leader。

但是这种⽅式有⼏个缺点:
split-brain。这是由ZooKeeper的特性引起的,虽然ZooKeeper能保证所有Watch按顺序触发,但并不能保证同⼀时刻所有Replica“看”到的状态是⼀样的,这就可能造成不同Replica的响应不⼀致。
herd effect。如果宕机的那个Broker上的Partition⽐较多,会造成多个Watch被触发,造成集群内⼤量的调整。
ZooKeeper负载过重。每个Replica都要为此在ZooKeeper上注册⼀个Watch,当集群规模增加到⼏千个Partition时ZooKeeper负载会过重。

基于Controller的选举⽅式

Kafka 0.8后的Leader Election⽅案解决了上述问题,它在所有broker中选出⼀个controller,所有Partition的Leader选举都由controller决定。controller会将Leader的改变直接通过RPC的⽅式(⽐ZooKeeper Queue的⽅式更⾼效)通知需为为此作为响应的Broker。同时controller也负责增删Topic以及Replica的重新分配。

优点:极⼤缓解了Herd Effect问题、减轻了ZK的负载,Controller与Leader/Follower之间通过RPC通信,⾼效且实时。
缺点:引⼊Controller增加了复杂度,且需要考虑Controller的Failover。

如何处理Replica的恢复


image.png

1:只有当ISR列表中所有列表都确认接收数据后,该消息才会被commit。因此只有m1被commit了。即使leader上有m1,m2,m3,consumer此时只能读到m1。
2:此时A宕机了。B变成了新的leader了,A从ISR列表中移除。B有m2,B会发给C,C收到m2后,m2被commit。
3:B继续commit消息4和5
4:A回来了。注意A并不能⻢上在isr列表中存在,因为它落后了很多,只有当它接受了⼀些数据,⽐如m2,m4,m5,它不落后太多的时候,才会回到ISR列表中。

思考:m3怎么办呢?
两种情况:

  1. A重试,重试成功了,m3就恢复了,但是乱序了。
  2. A重试不成功,此时数据就可能丢失了。

如果Replica都死了怎么办?
只要⾄少有⼀个replica,就能保证数据不丢失,可是如果某个partition的所有replica都死了怎么办?有两种⽅案:

  1. 等待在ISR中的副本恢复,并选择该副本作为Leader。
  2. 选择第⼀个活过来的副本(不⼀定在 ISR中),作为Leader。
    可⽤性和⼀致性的⽭盾:如果⼀定要等待副本恢复,等待的时间可能⽐较⻓,甚⾄可能永远不可⽤。如果是第⼆种,不能保证所有已经commit的消息不丢失,但有可⽤性。
    Kafka默认选⽤第⼆种⽅式,⽀持选择不能保证⼀致的副本。
    可以通过参数 unclean.leader.election.enable 禁⽤它。
Broker宕机怎么办?

Controller在Zookeeper的/brokers/ids节点上注册Watch。⼀旦有Broker宕机,其在Zookeeper对应的Znode会⾃动被删除,Zookeeper会fire Controller注册的Watch,Controller即可获取最新的幸存的Broker列表。
Controller决定set_p,该集合包含了宕机的所有Broker上的所有Partition。 对set_p中的每⼀个Partition:

  1. 从/brokers/topics/[topic]/partitions/[partition]/state读取该Partition当前的ISR。
  2. 决定该Partition的新Leader。如果当前ISR中有⾄少⼀个Replica还幸存,则选择其中⼀个作为新Leader,新的ISR则包含当前ISR中所有幸存的Replica。否则选择  该Partition中任意⼀个幸存的Replica作为新的Leader以及ISR(该场景下可能会有潜在的数据丢失)。如果该Partition的所有Replica都宕机了,则将新的Leader设置为-1。
  3. 将新的Leader,ISR和新的leader_epoch及controller_epoch写⼊/brokers/topics/[topic]/partitions/[partition]/state。
[zk: localhost:2181(CONNECTED) 13] get
/brokers/topics/bdstar/partitions/0/state{"controller_epoch":1272,"leader":0,"v
ersion":1,"leader_epoch":4,"isr":[0,2]}

直接通过RPC向set_p相关的Broker发送LeaderAndISRRequest命令。Controller可以在⼀个RPC操作中发送多个命令从⽽提⾼效率。
Controller宕机怎么办?
每个Broker都会在/controller上注册⼀个Watch。

[zk: localhost:2181(CONNECTED) 19] get /controller
{"version":1,"brokerid":1...............}

当前Controller宕机时,对应的/controller会⾃动消失。所有“活”着的Broker竞选成为新的Controller,会创建新的Controller Path

[zk: localhost:2181(CONNECTED) 19] get /controller
{"version":1,"brokerid":2...............}

注意:只会有⼀个竞选成功(这点由Zookeeper保证)。竞选成功者即为新的Leader,竞选失败者则重新在新的Controller Path上注册Watch。因为Zookeeper的Watch是⼀次性的,被fire⼀次之后即失效,所以需要重新注册

失效副本

Kafka中,⼀个主题可以有多个分区,增强主题的可扩展性,为了保证靠可⽤,可以为每个分区设置副本数。
只有Leader副本可以对外提供读写服务,Follower副本只负责poll Leader副本的数据,与Leader副本保持数据的同步。
系统维护⼀个ISR副本集合,即所有与Leader副本保持同步的副本列表。
当Leader宕机找不到的时候,就从ISR列表中挑选⼀个分区做Leader。
如果ISR列表中的副本都找不到了,就剩下OSR的副本了。
此时,有两个选择:要么选择OSR的副本做Leader,优点是可以⽴即恢复该分区的服务。缺点是可能会丢失数据。
要么选择等待,等待ISR列表中的分区副本可⽤,就选择该可⽤ISR分区副本做Leader。优点是不会丢失数据缺点是会影响当前分区的可⽤性。因为

副本复制
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容