Kafka怎么保证数据可靠?
往两大方向考虑问题:
一:如何保证数据不丢失?
1):副本同步机制:
kafka的partition为主从结构,在一个partition里,存在leader和follower,当数据发送给leader后,需要确保follower和leader数据同步后才发送给producer一个ack
副本同步实现-ISR副本同步队列:
ISR(In-Sync Replicas),副本同步队列。
ISR中包括leader和follower,如果leader挂掉,ISR队列会选择一个服务作为新的leader
有replica.lag.max.messages(延迟条数)和replica.lag.time.max.ms(延迟时间)两个参数决定一台服务是否可以加入ISR副本队列,0.10后把延迟条数删除防止服务频繁得进去队列。
任意一个维度超过阈值都会把 Follower 剔除出 ISR ,存入 OSR(Outof-Sync Replicas)列表,新加入的 Follower 也会先存放在 OSR 中。
为什么同步全部的副本数据:
- kafka由于会存放大量数据,不会去选择半数存活机制,半数会造成大量数据冗余。
- 因为都是部署在一个机架上的,所以网络延迟对kafka影响比较小
2):ack应答机制:
ack参数等级
- 0:producer不等待broker的ack,broker已接受到还没写入磁盘就返回成功,可能会造成数据丢失
- 1:producer等待broker的ack,partition的leader落盘成功返回ack,follower同步成功之前leader故障,数据可能会丢失
- -1(all):leader和follower全部落盘成功才返回ack**,当follow同步完成之后,leader挂了,producer又发了一次写入broker请求,结果在另外一个leader又写了一次,造成数据重复**
3):故障时副本一致性问题解决
LEO(log-end-offset):每个副本的最后一个offset
HW(high watemark):所有副本中最小的LEO
- follower故障:
follower会被踢出ISR,follower读取本地磁盘的记录得HW,高于log文件得全部删掉,从HW开始进行向leader同步
等该 follower 的 LEO 大于等于该 Partition 的 HW,即 follower 追上 leader 之后,就可以重新 加入 ISR 了。
- leader故障:
leader发生故障后,从ISR中选出一个新的leader之后,,之后,为保证多个副本之间的 数据一致性,其余的 follower 会先将各自的 log 文件高于 HW 的部分截掉,然后从新的 leader同步数据。
只能保证副本得数据一致性
二:如何保证数据不重复?
幂等性机制:
开启幂等性的 Producer 在初始化的时候会被分配一个 PID,发往同一 Partition 的消息会附带 SequenceNumber。而 Broker 端会对<PID,Partition,SeqNumber>做缓存,当具有相同主键的消息提交时,Broker 只会持久化一条。
但是 PID 重启就会变化,同时不同的 Partition 也具有不同主键,所以幂等性无法保证跨 分区跨会话的 ExactlyOnce
实现exactly once:
保证每条信息被发送且仅被发送一次
0.11后,kafka引入幂等性机制
(dempotent)(实例化一次机制),配合acks = -1时得at least once语义(会重复不丢失),完成了exactly once
只需将enable.idempotence属性设置为true,kafka自动将acks属性设为-1