Kafka的复制和备份
关于分区的几个总结:
- 一个分区a有一个首领broker A,且a是首领分区
- 一个分区可以在多个broker中存在副本,此时这些副本都是复制的首领分区的内容,而且生产者和消费者操作分区时,必须是首领分区。
- 如果一个broker失效,而且该broker中有一个或者多个首领分区,那么其余包含这些首领分区副本的broker,会重新选举并接替这个broker中首领分区的领导权。对应的生产者和消费者也会重连到含有首领分区对应的broker上
如下图:
假设Broker1中的含有首领分区Partition-0,其余的Partition-0的都是副本,其余broker以此类推。如果此时Broker1崩溃,那么Broker2中的Partition-0就成为对应的首领分区;同理Broker4的Partition-3也成为对应的首领分区,操作Partition-0和Partition-3的生产者和消费者会连接到Broker2和Broker-4上;上图中的复制系数是2
首领broker创建过程:
首领broker创建方式和zk的leader创建方式一致,所有的broker会向zk上的/controller创建临时节点,只有一个能创建成功,该节点就是首领broker,同时其余的broker会watch该节点,如果首领broker崩溃,则其余broker会收到通知,并重新进行选举。
节点使用epoch来标记首领,只承认收到的epoch最大的节点的消息作为首领节点。
broker崩溃
- 首领broker崩溃,则重新选举
- 非首领节点崩溃,则首领节点负责协调其它的broker接替;退出的broker仍然在元数据中
- 如果新节点加入,如果是之前崩溃的节点,则会复制对应的消息。
首领副本broker的任务:
每个分区会有一个首领分区和多个副本分区,首领分区的broker就是该首领副本的broker。注意这和首领broker是不同的。
首领分本broker任务:
- 向生产者和消费者提供服务
- 向其它副本broker提供复制数据,并监控其余副本broker的同步情况
只有持续从首领副本broker才是同步broker,当首领副本崩溃时,同步副本broker中的一个接替成为首领副本broker。。
注意一个概念,首领副本broker是针对分区的
Kafka处理请求
- 生产者消费者对分区的操作,必须经过首领副本分区,这是为了保证一致性。
- 每个broker都有元数据,该数据是ZK的,数据中包含了每个分区的首领副本broker等
- 客户端定期从任意一个broker获取元数据,而提交或获取数据的时候,是根据元数据的内容进行的
- 如果操作分区时,kafka集群已经发生了变更,则客户端会收到有关的错误,此时需要重新获取元数据,然后操作
生产者有acks参数,代表收到broker回复个数后,才认为是发送成功的。0表示只要发送完就成功;1表示只要首领副本broker收到,然后返回ack就行;acks=all表示所有的broker都受到才可以。
Kafka的存储细节
分区副本分配
kafka的最小存储单元是分区,分区不可再分。
kafka的分区分配以下原则:
- 在broker之间平均分配分区副本
- 确保每个分区的每个副本在不同的broker上
- 如果broker指定了不同的机架信息,则kafka会尽量保证副本在不同的机架上
文件管理
- kafka中的文件不会立刻删除,给消费者消费时,变化的仅仅是group的偏移量
- 每个分区的数据分段存储,正在写入的是活跃片段,删除的文件不会是活跃片段,只能是之前的片段
- 分区的片段,一般默认保存7天或者1GB,以较小的那个为准
- kafka生产者按照一个批次发送数据时,消费者
文件格式
Kafka把生产者发来的数据,按照原来的格式发送给消费者
一个消息的格式如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wqobk8Id-1581859968099)(en-resource://database/617:1)]
其中时间戳可以配置为生产者发送的时间或者到达broker的时间。如果一个消息按照批次压缩发送,如上图,则消费者获取对应的偏移量消息后,解压会得到整个批次的消息。
文件索引
以偏移量读取数据时,需要消费者主动提供偏移量,之后kafka会把偏移量映射到分区的文件地址上,文件存储格式就是指这个。
注意,kafka 分区本身不会记录每个消费者组消费的位置,需要消费者提供偏移量,kafka提供的仅仅是偏移量映射的地址(_consumer_offset_记录的是最后的偏移量)
上述的映射方式就是Kafka的索引,索引有以下几个特点:
- Kafka本身不维护索引的校验和
- 索引也分段,如果数据片段删除,则索引段也删除。
- 如果索引损坏,则kafka重新读取文件并重新生成索引,同样的也可以手动删除,让kafka重新生成。
文件删除
kafka默认的删除策略是根据时间和大小删除,这里介绍的是log compaction策略,可以理解为一种压缩日志的方式。说明一点,与基于时间和大小的方式一样,这种模式也是操作那些不再读写的片段
基本原理:
对于不活跃片段,只保留最近的键值,如上图所示。这种方式可以用来去重。
如果要删除某个值,则需要重新在对应的partition上上传相同的键值,把值设置为null即可。
参考:
- https://segmentfault.com/a/1190000007922290
- https://www.jianshu.com/p/3e0d426313aa
- https://cloud.tencent.com/developer/article/1481337