kafka使用high api如何确保不丢失消息,不重复发送,消息只读取一次?

https://www.zhihu.com/question/34842764/answer/138125661

kafka使用high api如何确保不丢失消息,不重复发送,消息只读取一次?

虽然low api可以通过offset来实现,但是感觉好麻烦
作者:雨夜偷牛的人
链接:https://www.zhihu.com/question/34842764/answer/138125661
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

首先说明,Kafka 的设计就是 at-least-once 的


那么,如何确保非极端环境下,Kafka 不丢数据,以及 Kafka 集群尽可能稳定呢?
  1. Producer 端设置 ack 为 all(或者说尽可能越多越好,但实际生产里集群实例过多,这样设置会影响性能,因此根据具体情况来定),即 确保所有 replication 都拿到数据的时候,send 方法才得以返回,以此来判断数据是否发送成功,那么理论上来说,此时发送成功的数据都不会丢失;
  2. unclean.leader.election.enable 设置为 false(默认参数为 true),意思是,当存有你最新一条记录的 replication 宕机的时候,Kafka 自己会选举出一个主节点,如果默认允许还未同步你最新数据的 replication 所在的节点被选举为主节点的话,你的数据将会丢失,因此这里应该按需将参数调控为 false;
  3. auto.offset.reset 参数设置为 earliest 避免出现 offset 丢失的时候,跳过需要消费的数据的情况,准确来说这里并非丢失,即使因为参数配置的问题出现跳过的情况,也可以通过前置 offset 找回历史消息;
  4. 数据持久化的时间需要设置业务足够接受的程度,我自己业务上使用就是能保证我的数据持久化时间为8个小时,超过8个小时的数据将被清空。

即使这样配置了,Kafka 在极端环境下也并非确保绝对不丢数据!!!


既然是极端环境的探讨,也就意味着能碰到的几率是非常低的,几率有多少我没统计过,其中第二种情况在业务中时常遇到。
  1. 根据 Kafka 官方文档说明,Producer 发送消息持久化到 Kafka 得到 ack 的回馈这段过程中,基于性能的考虑,Kafka 并没有及时把数据落盘的,而是将数据放到内存(FS cache)中,并周期性的落盘(从磁盘监控也可以看的出来),如果数据未及时落盘,如遇到服务器断电宕机,则数据丢失;
  2. 实际业务中,对数据可靠性较高的场景我建议手动提交 offset,自动提交 offset 会出现一个比较尴尬的情况,在业务应用被 kill 之前, A 消息的offset 可能被提交了,然而 A 消息在应用系统中尚未执行完毕,且状态都保存在了内存中,无法保留,此时重启应用将不会继续消费 A 消息,而是神不知鬼不觉的跳过。当然这种情况也并非算得上丢失数据,重置 offset 一样可以找的回来,但是手动提交 offset 可以避免这种诡异的情况发生。

Kafka HA 如何保障?
官方的意思是尽可能多节点集群部署,节点数尽可能大于等于3,并且 replication 数量也是大于等于3,那么当 replication 数量为 N 时,ack 设置为 all,这种情况下,就能确保 N-1台机子宕机的时候,数据仍能保持不丢。

另外补充,既然是at-least-once,肯定会出现重复消费的情况,这个不难解决,Consumer 保持无状态和幂等性就可以了。

Kafka本身是不能保证“消息只读一次”,需要借助其他办法保证,比如2PC等,但是如果使用分布式事务的话,会影响吞吐量的。另外Kafka本身就是为了高吞吐量而设计的,如果非要保证“消息只读取一次”,可以使用JMS。
另外,说句题外话——每一个框架被设计的时候,都有考虑特定的使用场景的,比如Kafka就比较适合高吞吐量并且允许少量数据丢失的场景,所以一定要根据应用业务和使用场景来做技术选型。


Kafka通过多个方面来保证消息的不丢失。首先,Kafka的每条消费都会被存储到磁盘上进行持久化存储,即使broker因为异常进行重启,也不会消息丢失。此外,Kafka以集群的方式进行部署,并且通过分区和副本的特性来保证broker端的消息丢失。\[1\] 其次,Kafka采用了不同的发送数据模式来保证消息的不丢失。同步发送模式要求在发送一条消息后,必须阻塞等待收到通知后,才发送下一条消息确保消息被成功写入队列中。异步发送模式则是将消息写入缓冲区,然后一次性写入队列中,提高了发送效率。\[2\] 此外,Kafka使用了ack机制来确保消息的正常收到。在发送数据时,每次发送消息都会有一个确认反馈机制。通过设置参数acks的值,可以控制消息的确认方式。如果设置为0,代表发送后不等待Kafka消息确认,可能会丢失消息。如果设置为1,代表发送后等待leader副本确认消息确保消息被写入分区文件。如果设置为all,代表发送后等待消息被写入所有同步副本之后才认为成功。\[3\] 需要注意的是,all代表所有同步副本,而不是所有副本。具体的同步副本数量取决于Kafka集群设置的最小同步副本数和当前的同步副本数。选择较高的同步副本数可以提高可靠性,但会牺牲一定的效率。可以通过增大批次和使用异步模式来提高效率。\[3\] #### 引用[.reference_title] - *1* [kafka如何保障数据不丢失](https://blog.csdn.net/weixin_42910501/article/details/130167743)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [Kafka 保证消息的不丢失](https://blog.csdn.net/qq_43081842/article/details/101212278)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值