架构概述
kafka的架构非常值得学习和借鉴。
kafka本身是主从关系的,broker的角色可以有controller与普通节点的划分,controller节点除了需要承担普通节点的功能,还需要与zookeeper协作管理集群元数据。同时,各个broker上后台线程监测到元数据变化的时候,会通知其他broker,例如lsr收缩,每个broker上也会保存一份元数据,当对元数据的请求到来的时候可以快速响应。
为了水平扩展,kafka中设计partition分区的概念,对于生产者和消费者而言topic是逻辑抽象概念,写入的每条消息都要设定topic,代表一类消息,实际物理上是按照partition来分的,一个topic中分为n个partition,每个partition内采用append的方法高效快速写入消息,用offset来表征消息,每个log segment都由的形式构成,同时每个log segment还有对应的索引文件。如果有多个partition,只能保证partition内部的有序性,无法保证topic即partition之间消息的有序性。kafka会保存所有的消息,不管是否消息已经被消费了,这是有别于其他消息中间件的地方,对于数据删除有两种策略,一个是时间,还有一个是文件大小。
采用了partition后类似每个服务实例处理一部分消息,本地存储部分消息,适用于生产者与消费者无需感知消息顺序,且无状态(即某个请求需要获取的状态信息不需要判断在哪台实例上),生产者只需要append,消费者只需要消费即可。
为了保证系统的可靠性,kafka采用了复制备份的策略,每个partition都有备份,提高了可用性的情况下会对吞吐有略微影响。broker上服务起来后,会启动replicaManager管理副本,根据元数据判断broker是follower还是leader,follower副本会不停的向leader副本发送fetch请求,获得response后将records写入本地log并更新LEO和HW来达到同步的目的。在zookeeper会维护一个ISR列表,里面存储的是与leader副本保持同步的follower副本,其中的broker满足两个条件,一个是与zookeeper保持heartbeat,二是落后leader在一定的范围和时间内,这样当leader宕机的时候才能保证从ISR中选举出来的新leader与老leader保持数据一致,同时,可以通过在写入数据的时候配置ac