消息不丢失:生产者收到写入成功响应后消息一定不会丢失吗?

消息不丢失:生产者收到写入成功响应后消息一定不会丢失吗?

理解消息丢失,需要对生产者到消费者整个环节都有深刻的理解

Kafka主从同步与ISR

  • kafka中消息被存在分区中。为了避免分区所在的服务器宕机,分区也是主从结构的。不同的分区之间是一个对等的结构,每一个分区其实是由一个主分区和若干个从分区组成的
  • 主从分区都放在broker上,但是在放某个topic分区时,尽量做到一个broker上只放一个主分区,但是可以放别的主分区的从分区
  • 避免broker崩溃影响多个主分区

写入语义

写入消息时,既可以是写入主分区,也可以是写入主分区后再写入一部分从分区

  • kafka就比较灵活,使用了acks来控制
  • acks=0:发送后就不管了,也就是说broker是否收到,收到后是否持久化,是否主从同步,全都不管
  • acks=1:当主分区写入成功时,就认为发送成功
  • acks=all:不仅写入了主分区,还同步给了所有ISR成员

ISR

  • ISR指和主分区保持主从同步的所有从分区。
  • 可以通过配置min.insync.replicas配置。比如这个这个值为2时,就说明ISR中至少2个从分区,如果分区数不足,acks=all时,发送消息会失败

消息丢失的场景

生产者发送

  • acks=0时,可能broker没有收到消息,或者处理消息时出现了bug
  • 启用批量发送功能时,批次较大可能导致kafka连请求都没有发送出去,服务崩溃,也会丢失

主从同步

  • acks=1时,只要求写入主分区。假设在写入主分区后,主分区的broker立刻崩溃。这个时候就会重新选举新的主分区,不管哪个分区被选上都缺少这条消息
  • acks=all时,kafka还有一种unclean选举。在允许unclean选举时,如果ISR没有任何分区,就会选择第一个分区作为主分区。但是新选出来的主分区可能缺少部分数据

生产者发送和主从同步解决方案

  • 设置acks=all,并禁用unclean选举
  • 但是这并不是万无一失的,还要考虑刷盘

刷盘

kafka刷盘,要么是定时刷 ,要么是定量刷

kafka控制刷盘的参数有三个

消费者提交

消费者提交指消费者提交了偏移量,但却没有消费的情况。

  • 比如,线程池形态的异步消费,消费者线程拿到消息就直接提交,然后再转交给工作线程。在转交前,或者工作线程处理时,消费者宕机。导致一个未被消费的消息被提交了

解决方案

发送方一定发送了消息

  • 可以采用本地消息表或消息回查
本地消息表
  • 在发送方,采用本地消息表解决方案。在业务操作过程中,在本地消息表里记录一天代发消息,做成本地数据库事务。然后尝试立刻发送消息,如果成功就把本地消息表里对应数据删除或标记已发送。
  • 如果失败就立即重试。同时还有一个异步补发机制,扫描本地消息表,找出长时间没有发送成功的消息。比如三分钟没有发送成功,扫描到后补发

消息队列不丢失

  • 把acks设置成all并禁用unclean选举,确保消息发送到消息队列,且不丢失。同时刷盘的三个参数设置成10000,2000,3000。
  • 理论上说可能还是会丢失一点消息,但是概率很低。只有一种可能,就是消息队列完成主从同步后,主分区和ISR的从分区没来得及刷盘就挂了,才会导致消息丢失,此时消息是真的丢失了,只能人工补发

消费者肯定消费

  • 确保消费者肯定消费,大多数时候不需要做什么操作,但是如果使用了异步消费机制就需要考虑了
  • 如A业务采用异步消费提高消费速率,只要利用批量消费、批量提交保证异步消费,也不会出现未消费问题

亮点方案:在kafka上支持消息回查机制

消息回查指消息队列允许在发送消息的时候,先发一个准备请求,里面带着消息。这个时候消息队列并不会把消息传给消费者,而是业务完成后,需要再发一个确认请求,这个时候中间件才会把消息转交给消费者

  • kafka不支持回查机制。可以自己设计一个回查功能的系统

  • 1.业务代码把准备消息发送到topic=look_back_msg上

    • 里面包含业务topic、消息体、业务类型、业务ID、准备状态、回查接口
  • 2.回查中间件把准备消息存储到数据库

  • 3.业务代码执行完操作后,再发一个消息到look_back_msg上

    • 带上业务类型、业务ID和提交状态,如果应用代码执行错误,那么就使用回滚状态
  • 4.回查中间件查询消息内容,转发到业务topic上

亮点一:回查实现
  • 回查中间件要知道怎么回查应用代码

    • 回查机制要设计成可扩展的,可以回查HTTp接口,也可以回查RPC接口
  • HTTP

    • POST方法
    • Body带上业务类型和业务ID
    • 业务方提供回查URL
  • RPC:一般使用泛用化调用

亮点二:数据存储
  • 为了保证会查机制的高性能和高可靠,使用了分区表。按照时间分区,并且历史分区是可以快速归档的,因为回查机制的数据库只是临时存储一下消息数据。考虑后续业务拓展。也可以按照业务topic来分库分表
亮点三:有序消息
  • 同一个业务的准备消息一定先于提交消息

    • 可以在发送时要求业务方按照业务ID计算一个哈希值,然后除以分区数量的余数就是目标分区。从而实现有序消息
相关推荐
高兴达16 分钟前
Spring boot入门工程
java·spring boot·后端
到账一个亿2 小时前
后端树形结构
后端
武子康2 小时前
大数据-31 ZooKeeper 内部原理 Leader选举 ZAB协议
大数据·后端·zookeeper
我是哪吒2 小时前
分布式微服务系统架构第155集:JavaPlus技术文档平台日更-Java线程池实现原理
后端·面试·github
代码老y2 小时前
Spring Boot + 本地部署大模型实现:安全性与可靠性保障
spring boot·后端·bootstrap
LaoZhangAI2 小时前
OpenAI API 账号分层完全指南:2025年最新Tier系统、速率限制与升级攻略
前端·后端
红衣信3 小时前
前端与后端存储全解析:从 Cookie 到缓存策略
前端·后端·面试
Kyrie_Li3 小时前
(十五)Spring Test
java·后端·spring
WildBlue3 小时前
🎉 手写call的魔法冒险:前端开发者的“换身份”指南🚀
前端·后端
fortmin3 小时前
使用Apache Pdfbox生成pdf
后端