实际业务处理 Kafka 消息丢失、重复消费和顺序消费的问题

消息丢失,消息重复消费,消息顺序消费等问题是我们使用 MQ 时不得不考虑的一个问题,下面我结合实际的业务来和你分享一下解决方案。

比如我们使用 Kakfa 时,以下场景都会发生消息丢失:

  • producer -> broker (生产者生产消息)
  • broker -> broker (集群环境,broker 同步给其他 broker)
  • broker -> consumer (消费者消费消息)

解决方案也很简单,设置 acks(消息确认机制) retries(重试机制) factor(设置 partition 数量)…

一般来说,最常见的消息丢失场景就是: consumer 消费消息

要保证 consumer 消费消息时不丢失消息,必须使用 手动提交 ack

我们业务是这样实现的:

要解决消息重复消费,也就是要实现 幂等(幂等就是:多次请求,但结果保持不变,举一个例子你就明白了: 在 http 中,你发送同一个 get 请求,无论发送多少次,返回结果都是一样的

回到我们的业务场景上,我以处理订单消息为例:

  • 幂等Key 由我们的 订单Id + 订单状态组成(一笔订单的状态只会处理一次)
  • 在处理之前,我们首先会去 Redis 查询是否存在这个 Key 如果存在,说明我们已经处理过了,直接丢掉; ​ 如果不存在,说明没处理过,继续往下处理;
  • 最终的逻辑是:将处理过的数据存到 DB上,再把 幂等Key 存到 Redis

显然一般场景下 Redis 是无法保证幂等的

所以 Redis只是一个 前置处理,最终的幂等性依赖 DB唯一Key(订单Id+订单状态)

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

消息的顺序性很好理解,还是以订单处理为例

订单的状态有:支付、确认收货、完成等等,而订单下还有计费、退款的消息报

理论上来说:支付的消息肯定要比退款的消息先到。

但是程序处理的过程就不一定了,所以我们处理消息顺序消费的流程如下:

  • 宽表:创建一张宽表,唯一索引是 订单Id,将订单的 每个状态拆分为一个列,当消息来了,只更新对应的字段就好,消息只会存在短暂的状态不一致问题,但是最终状态是一致的
  • 消息补偿机制
  • 把相同的 userID/orderId 发送到相同的 partition(因为一个 consumer 消费一个 partition)

Original: https://www.cnblogs.com/Fzeng/p/16102422.html
Author: 小冯同学c
Title: 实际业务处理 Kafka 消息丢失、重复消费和顺序消费的问题

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/592981/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • PHP生成图形验证码

    在建站过程中,很多时候都会需要用户验证验证码等操作,比如:注册、登录、发表评论、获取资源等等,一方面可以验证当前用户的行为是否是爬虫、机器人等情况,给网站数据统计产生影响;另一方面…

    Java 2023年6月10日
    078
  • Java-Dubbo学习及整合SpringBoot

    Dubbo是Java的RPC框架,具有三大核心功能:面向接口的远程方法调用,智能容错和负载均衡,以及服务的自动注册和发现 Dubbo架构图: 节点角色说明: 节点 说明 Provi…

    Java 2023年6月8日
    081
  • 01第一章:01_RocketMQ概述

    一、MQ 简介 MQ,Message Queue,是一种提供 消息队列服务的中间件,也称为消息中间件,是一套提供了消息生产、存储、消费全过程 API 的软件系统。消息即数据。一般消…

    Java 2023年5月29日
    066
  • 动力节点-王妈妈Springboot教程(六)Redis

    *官方下载地址:动力节点官网 *视频观看地址 Redis : 一个NoSQL数据库, 常用作缓存使用 (cache) Redis的数据类型: string , hash ,set …

    Java 2023年6月7日
    089
  • 利用订阅模式实现缓存更新

    1. 引言 很多Web项目,都需要和数据库打交道,典型的就是CRUD(读,写,更新,删除)操作。无论是哪种数据库,Asp.Net MVC 作为后端框架的项目,都有很多操作数据库的类…

    Java 2023年6月5日
    059
  • 并发QPS公式估算

    一、经典公式1: 一般来说,利用以下经验公式进行估算系统的平均并发用户数和峰值数据 1)平均并发用户数为 C = nL/T 2)并发用户数峰值 C’ = C + 3*根…

    Java 2023年6月15日
    076
  • 延时任务-基于redis zset的完整实现

    所谓的延时任务给大家举个例子:你买了一张火车票,必须在30分钟之内付款,否则该订单被自动取消。 订单30分钟不付款自动取消,这个任务就是一个延时任务。 我之前已经写过2篇关于延时任…

    Java 2023年6月15日
    088
  • Spring AOP 切点切面

    Spring AOP 切点切面 https://www.jianshu.com/p/94879042db88 https://www.jianshu.com/p/994027425…

    Java 2023年5月30日
    074
  • SqlSessionFactory工具类抽取

    多次SqlSessionFactory创建对象问题解决 SqlSessionFactory工具类抽取 问题描述: 当我们多次使用SqlSessionFactory创建并获取对象时会…

    Java 2023年6月6日
    088
  • Mall 动态权限学习参考

    代码仓库 https://github.com/Rain-with-me/JavaStudyCode/tree/main/4-springboot-security-dynic 本…

    Java 2023年6月16日
    081
  • Zookeeper-3.4.9安装

    环境: centos7 Zookeeper-3.4.9.tar.gz 官网下载 步骤 下载后上传压缩文件并解压 tar -zxvf zookeeper-3.4.9.tar.gz -…

    Java 2023年6月7日
    0100
  • 方法是什么

    什么是方法? System.out.println(),这是方法,输出语句的方法 这句语句就是调用系统System类中的标准输出对象out中的println()方法。 (类+对象+…

    Java 2023年6月9日
    0116
  • TODO NAVIGATOR

    1.网址导航 地址 分类 备注基于 Flink+Hive 构建流批一体准实时数仓 Data拜托,面试请不要再问我Redis分布式锁的实现原理【石杉的架构笔记】 秒杀系统 3种Red…

    Java 2023年6月5日
    076
  • MyBatis 结果映射总结

    前言 结果映射指的是将数据表中的字段与实体类中的属性关联起来,这样 MyBatis 就可以根据查询到的数据来填充实体对象的属性,帮助我们完成赋值操作。其实 MyBatis 的官方文…

    Java 2023年6月9日
    082
  • Java8——Stream流式操作的一点小总结

    我发现,自从我学了Stream流式操作之后,工作中使用到的频率还是挺高的,因为stream配合着lambda表达式或者双冒号(::)使用真的是优雅到了极致!今天就简单分(搬)享(运…

    Java 2023年6月5日
    077
  • DeferredResult异步处理spring mvc Demo

    spring mvc同步接口在请求处理过程中一直处于阻塞状态,而异步接口可以启用后台线程去处理耗时任务。简单来说适用场景:1.高并发;2.高IO耗时操作。 Spring MVC3….

    Java 2023年5月29日
    066
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球