Kafka数据问题

1. Kafka会丢数据吗?

1.1 Kafka可能会丢消息的场景

1.1.1 Producer向Broker发消息时

producer -> broke

解决方案:选择带有 callBack 的api进行消息发送(设置 acks、retries、factor等参数来保证数据一致)如果发送成功了,会回调告诉你已经发送成功了;如果失败了,那收到回调之后自己在业务上做重试就好了。

注意以下场景:

1. 消息发送broker失败但callback api由于某种原因没有被触发的场景。

2. 把相同userId/messageId发送到相同的patition时,kafka扩容rebalance时怎么处理消息。

1.1.2 消息发送到Broker后

broker -> broker之间同步

        一般线上都是集群环境,如果发送消息后broker挂了,此时该broker还没来得及把数据同步给其它broker,数据就自然就丢了。

1.1.3 Broker存储数据时

broker -> 磁盘

        Broker把数据存储到磁盘之前,走的是操作系统缓存,异步刷盘这个过程有可能导致数据丢失。

1.2 client 消费 broker 丢消息

这个场景丢消息会比较多

1.2.1 消费数据时怎么保证数据的可靠性?

        首先,要想client端消费数据不能丢,必须手动提交,不能使用autoCommit。

1. 从Kafka拉取消息时(一次批量拉取500条,这里主要看配置),为每条拉取的消息分配一个msgId(递增);

2. 将msgId存入内存队列(sortSet)中,使用Map存储msgId与msg(有offset相关的信息)的映射关系;

3. 当业务处理完消息后,ack时,获取当前处理的消息msgId,然后从sortSet删除该msgId(此时代表已经处理过了);

4. 接着与sortSet队列的首部第一个Id比较(其实就是最小的msgId),如果当前msgId<=sort Set第一个ID,则提交当前offset;

5. 系统即便挂了,在下次重启时就会从sortSet队首的消息开始拉取,实现至少处理一次语义;

6. 会有少量的消息重复,但只要下游做好幂等就OK了。

丢数据的场景:从kafka拉取消息下来,由于自动的提交模式已经提交了offset,但消费者是没有真正消费成功的,并且消费者可能日常发布重启或者挂掉了,那这条消息就丢了。自动提交不由消费者可控,而消费者才是真正知道是否消费成功的一方。

1.2.2 怎么实现幂等性呢?

通过Redis做前置处理,DB唯一索引做最终保证来实现幂等性的。

以处理订单消息为例:

        幂等Key由订单编号+订单状态所组成(一笔订单的状态只会处理一次)在处理之前,首先会去查Redis是否存在该Key,如果存在,则说明已经处理过了,直接丢掉。如果Redis没处理过,则继续往下处理,最终的逻辑是将处理过的数据插入到业务DB上,再到最后把幂等Key插入到Redis上。

        显然,单纯通过Redis是无法保证幂等的,Redis其实只是一个「前置」处理,最终的幂等性是依赖数据库的唯一Key来保证的(唯一Key实际上也是订单编号+状态)。

1.1.3 顺序消费问题

一个例子:

        订单的状态比如有 支付、确认收货、完成等,而订单下还有计费、退款的消息报理论上来说,支付的消息报肯定要比退款消息报先到,但程序处理的过程中可不是一定的所以在这边也是有消费顺序的问题,但在广告场景下不是「强顺序」的,只要保证最终一致性就好了。

处理「乱序」消息的实现:

1. 宽表:将每一个订单状态,单独分出一个或多个独立的字段。消息来时只更新对应的字段就好,消息只会存在短暂的状态不一致问题,但是状态最终是一致的。

2. 消息补偿机制:另一个进行消费相同topic的数据,消息落盘,延迟处理。将消息与DB进行对比,如果发现数据不一致,再重新发送消息至主进程处理。

3. 还有部分场景,可能我们只需要把相同userId/orderId发送到相同的partition(因为一个partition由一个Consumer消费),又能解决大部分消费顺序的问题了呢。

哪有不丢数据的,没有什么是绝对的。关键看一致性算法补偿机制等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值