Kafka & RocketMQ 关于数据丢失的态度和策略

kafka & rocketmq 关于自身应用的场景#

技术是服务于业务的,当我们在思考为什么kafka可以容忍少量数据丢失,而rocketmq不能容忍数据丢失时,我们就不能不考虑它们所面临的业务场景

  1. kafka 日志采集、监控指标、实时统计、IoT 设备数据等
  2. rocketmq 交易、支付、订单、物流等金融级场景

kafka & rocketmq 关于数据丢失的场景#

kafka#

生产端丢失#

  1. acks=0生产者发完直接认为成功,网络抖动、broker 宕机都会丢数据.acks=1:仅主分区落盘就返回,主副本刚写入就宕机,副本未同步 → 丢数
  2. 发送失败不重试 / 重试次数为 0

服务端丢失#

  1. 未开启日志刷盘(默认刷盘策略)
  2. 副本同步不及时 + leader 宕机 高水位 HW 未推进,新消息只在 leader、没同步到 follower,leader 宕机选新主 → 丢未同步数据
  3. 分区副本数 = 1 单副本无备份,机器故障必然丢部分数据

消费者端丢数#

  1. 自动位移提交(默认)+ 消费未完成就提交 offset
  2. 手动提交 offset 时机错误

rocketmq#

生产者端:强确认 + 重试,避免发了就丢#

3 种发送模式#

  1. Oneway:只管发、不等应答(类似 Kafka acks=0),丢得最多,适合日志
  2. 异步发送 + 回调:发完就走,回调里处理失败;不写回调会丢
  3. 同步发送(默认推荐):send() 阻塞,直到 Broker 明确返回写入成功才认为发送完成

自带重试#

同步发送失败默认重试 3 次,可配置;网络抖动、主从切换时比 Kafka 更稳

Broker 端:刷盘 + 主从双保险#

  1. 刷盘策略 ASYNC_FLUSH(默认):写 PageCache 就返回,后台异步刷盘 SYNC_FLUSH:写 PageCache 刷盘完成后再返回,同步刷盘,耗时长
  2. 主从复制 ASYNC_MASTER:主写成功立即返回,异步复制给从;主挂可能丢少量 SYNC_MASTER2:主写成功后,同步复制给从
  3. 存储结构 CommitLog 顺序写、ConsumeQueue 索引异步写;只要 CommitLog 不丢,索引丢了可重建,数据更安全

消费端:手动 ACK + 重试 + 死信队列,防止 “消费中丢”#

  1. 必须手动 ACK:消费成功后调用 message.ack();没 ACK 会一直重发
  2. 自动重试:消费异常(数据库失败、超时)→ 不 ACK → Broker 重新投递
  3. 死信队列:重试 16 次仍失败 → 进死信队列,人工处理,不丢