保证kafka数据不丢失,即保证生产者、消费者、broker三个部分数据不丢失。
一、保证生产者数据不丢失
为了保证生产者发送的数据已经发送到了broker,需要broker在接收到producer发送的数据时,返回消息确认ack。
在设计broker的ack时,需要考虑到三个问题:
- 问题1:broker一直没有ack状态,producer无法知道broker是否成功接收到消息?
解决方案:设置超时时间,比如10s,超时表示失败,设置重试次数,超过重试次数,则报错。
- 问题2:每条消息都回复ack,会不会比较占用网络资源?
解决方案:引入缓冲池,生产者现将数据放入到缓冲池,达到一定阈值或者时间阈值后进行发送,会影响消息的实时性。
- 问题3:缓冲池中积累的消息按500条发送后,broker没有ack,如何处理缓冲池中的数据?
解决方案:如果buffer满了,根据需要可以设置清空或者不清空。
1.1 kafka的设计
1.1.1 ack状态的设计
broker到producer的ack设计需要考虑两种场景:partition的leader确认ack和所有副本同步完成的确认ack,所以kafka对于broker给producer的ack的状态设计如下:
- 0:生产者只负责发送数据
- 1:某个partition的leader收到数据并给出响应
- -1:某个partition的所有副本都收到数据后给出响应
1.1.2 异常处理设计(broker没有ack)
同步模式,即没有缓冲池
- 生产者等待10s,如果broker没有给出响应,则认为失败
- 失败了重试3次发送,3次都失败,跑错
异步模式,即使用缓冲池
- 缓冲池设计消息数量阈值和时间阈值,保证消息的及时发送
- 当broker没有ack时,可以根据需求设计buffer是否清空
二、保证broker数据不丢
(1)使用partition的副本机制
(2)使用broker-producer的ack -1状态,保证所有副本已经同步到数据
三、保证消费者数据不丢
通过offset(偏移量) commit来保证消费到所有的数据,kafka记录group id对应的消费offset数值,下次可以继续接着offset消费。
offset信息在kafka0.8版本之前是记录在zookeeper中,在0.8之后的版本记录在topic中,即消费者在运行过程中挂掉了,再次启动的时候,会找到offset的值,找到之前消费信息的位置,接着offset往下消费。
由于offset的提交是在消费消息之后,所以如果消费者消费完消息,还没有来得及提交offset,消费者端挂掉了,这样消费者重新起来后,会存在重复消费的情况。
四、总结
直接引用Lansonli的图
生产者端:
消费者端