1、名词解释
1. 根本名词
- 主题:topic。逻辑概念,用于辨别业务
- 服务器:broker。接管长久化音讯,治理topic,权限治理,consumer重均衡等等
- 分区:partition。一个有序的音讯序列,一个topic对应多个分区
- 音讯:record。不做解释
- 音讯位移:Offset。分区中每条音讯的地位
- 生产者:producer。不做解释~~~~
- 消费者:consumer。不做解释
2.正本与ISR
这两个是broker外面的两个概念名词。
所谓_正本_,就是kafka为了进步可用性,将同一个parition数据扩散到不同broker的数据备份。同时kafka会选出一个leader正本用于对外读,follower则须要被动向leader正本申请同步kafka日志,以保障主从正本数据保持一致。
所谓_ISR_,就是有资格能被评比为leader正本的follower正本汇合。只有leader和ISR中所有正本都同步状态了,才会被kafka认为该音讯曾经提交。
3、正本中的概念
起始位移( base offset ):该正本第一条音讯的位移
高水印值( high watermark, HW ):该正本最新一条_曾经提交_的音讯位移。_如果某个音讯的offset小于该值,则所有的正本都曾经同步这条音讯了;如果某个音讯的offset大于该值,则肯阐明些正本还没同步到这条音讯_。换一种说法,所有offset小于该值的音讯对consumer是可见的;而大于该值的是不可见的。该值十分重要,他的值影响到正本主从同步的地位,影响到consumer生产数据的地位。应该留神的是,HW不止在leader里存在,在follower里也存在,其起因就是为了避免leader解体,follower也能立刻顶替leader进行失常工作(最终一致性)。
日志末端位移 (Clog end offset, LEO ):该正本最初一条信息的位移
2、音讯同步流程
1、整体流程
①broker1上的 leader 正本接管到音讯,把本人的 LEO 值更新为 1 。
②broker2 和 broker3 上的 follower 正本各自发送申请给 broker 1。(个别状况下,是follower定时给leader发送fetch申请的,就如同heartbeat心跳)
③broker1收到fetch申请后,被动别离把该音讯推送给 follower 正本 。
④follower 正本接管到音讯后各自更新本人的 LEO 为 1,并返回response。
⑤leader 正本接管到其余 follower 正本的数据申请响应( response )之后,更新 HW 值为 1 。 此时位移为 0 的这条音讯能够被 consumer 生产。
2、流程细节
_准则:HW是以后已知的所有LEO的最小值_。为什么呢?失常状况下,各个broker的partition数据都是程序写入的,最小的LEO意味着所有的正本都同步到了这个LEO以前的所有数据,就满足了“HW之前的音讯都曾经同步实现”的要求。
为了便于形容,咱们假如有两个正本在同步数据,一个leader一个follower
第一轮fetch
在某一时刻,leader收到了一条信息,写入了底层数据,接下来就是数据同步的过程了。
1、leader的LEO +1,好了解,有了一条信息,尾数须要加一。
2、leader尝试更新HW,取所有正本LEO最小值,本例是0。那么,哪里获取各个正本最小值呢?leader正本本地有个中央专门负责缓存这个数据,其余follower通过fetch申请告知leader
这个时候,follower发送了fetch(fetch申请里会带着本人当初的LEO,当初是0),leader收到了fetch
3、leader收到了fetch,尝试更新HW。所有正本LEO最小值。本人的是1,fetch里是0,那么是0。
4、获取offset >follower LEO的数据放到response里,同时将本人的HW(留神!!此时是全局LEO最小值)放到response里,本例里是0
5、follower承受到了response,将数据写入,同时更新LEO,本例里+1
6、follower尝试更新HW,是全局LEO最小值,比拟response里的HW和本人的LEO取最小值即可(下面红字的个性,这里就用到了)。本例里更新后是0
此时第一轮fetch完结,应该留神到,第一轮fetch实现后,数据尽管同步过来了,然而还不可见,因为leader此时还不晓得follower是不是同步胜利了
第二轮fetch
1、follower发送了fetch申请,携带本人的LEO=1
2、leader尝试更新HW,全局LEO的最小值,因而是1
3、获取offset >follower LEO的数据放到response里,这次没有数据,同时将本人的HW=1放到response里
4、follower收到信息,没数据写入,而后尝试更新本人的HW,全局最小值,本例HW=1
此时第二轮fetch完结,此时此刻,数据同步才真正完结,这条新数据对外可见了
3、数据失落问题
综合下面的阐述,通过两轮fetch过程后才会对外可见。这个时间差就容易导致数据失落或者不统一的问题
场景一:两轮fetch两头产生follwer和leader先后解体,前提:leader写入实现即认为已提交
如图,如果第二轮fetch产生,A曾经更新了HW,然而还没有包装response返回给B,此时B产生了解体。重启后的B会将LEO调整成解体前的HW值,那么前面的数据就被删除了(看,此时呈现了一次数据不统一)。这个时候B想要向A发动fetch,如果这个时候恰好A挂掉了,B被选为leader,A重启回来后就会fetch取leader的HW和本人的LEO比拟取最小值,最初失去HW=1,这样原来HW=2的数据就永恒失落了。
场景二:两轮fetch中,follower和leader同时解体
还是下面那种状况,第二轮fetch产生,A曾经更新了HW,然而还没有包装response返回给B。这个时候leader和follower同时解体,而后B先重启成为leader了。这个时候,producer发送了一个音讯记录到B,此时因为没有follower,因而间接更新HW到2。而后A回来成为follower,这时,A发现自己的HW和B的HW相等,因而不做变更。然而A的HW指向的音讯和B的HW指向的音讯并不是一回事,这显然就不是咱们想要的了。
4、数据失落问题的解决
kafka 0.11版本之后引入了leader epoch(我了解其实就是带有版本信息的HW)来取代HW,同时重启后的follower减少了一种申请,解决了这个问题。(这也是为啥商业应用基本上都用0.11之后的版本)。epoch实际上是一对值(epoch,offset)。 epoch 示意 leader 的版本号,offset示意本次写入的地位。比方(0,0)就代表这是第一次写入,写入地位是0 。(1,120)就代表,这是第二次写入,写入地位是120(后面曾经写了119个数据)
场景一的解决:
场景二的解决:
**附录:leader 中HW的更新条件**1. 正本成为leader正本的时候2. 集群里有broker解体,退出ISR的时候3. producer向leader推送数据的时候