预备知识:kafka的消息可以分成不同的topic,一个topic中的消息分布在不同的partition中,一个partition有多个副本,这些副本都叫AR(assigned replica),分为一个leader和多个follower。
分布式的一个核心技术就是复制。我们需要研究的问题是:follower是怎样从leader那里同步数据的?
先来看下单个AR,都有哪些特点?
每个副本都有LEO(Log End Offset), 它指向下一条要写的东西。
每个副本都有HW(High Watermark), 它表示消费者能拉取的最大消息的偏移量。
LEO和HW都是递增的。
partition的读和写都是通过leader进行的,而非读写分离。读写分离的缺点是,在一个时间窗口内,主从的数据可能不一致。
当生产者把消息发送给kafka后,怎样才算是commit(写入kafka)呢?
kafka有以下选择:
- 同步复制:等待所有follower同步完,这种方案的数据一致性好,但是吞吐量小。
- 异步复制:只要leader写入数据,立即commit,以后再同步followr。这种方案的吞吐量大,但是数据一致性差。
- ISR(In-Sync-Replicas):是所有副本的一个子集。如果一个follower落后leader不超过某个时间阈值,那么则则ISR中,否则将放在OSR中。
follower会不断尝试pull消息,完成同步。
follower有HW,一旦follower向Log写完数据,它会更新HW。具体算法是比较当前LEO和fetch响应中的leader的HW值,取两者中的较小者,作为新的HW值。这说明follower的HW值不会大于leader的HW值。
当follower同步完消息以后,会更新LEO+=1。
当数据同步完成以后,leader会比较所有ISR的LEO,选择最小的LEO作为HW。
BTW:
这篇文章是早就该写的,因为这个问题我很早就想过,但是很晚才去行动。
另外,我觉得这种学习方式非常落后,因为还停留在中学阶段。真正的研究要从实践和应用中去寻找问题、发现问题,这样才能真正拓展思维和知识的纵深。
否则,文章写得再精致,只是记住了一些“死”知识罢了,不会进步。
参考文章:
https://link.zhihu.com/?target=https%3A//blog.csdn.net/qq_34796981/article/details/80820302
https://link.zhihu.com/?target=https%3A//blog.csdn.net/u010003835/article/details/88683871
https://link.zhihu.com/?target=https%3A//www.jianshu.com/p/f5f173ab8b94
https://link.zhihu.com/?target=https%3A//blog.csdn.net/qq_37502106/article/details/80271800