我的编程空间,编程开发者的网络收藏夹
学习永远不晚

分布式面试消息队列解决消息重复保证消息顺序

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

分布式面试消息队列解决消息重复保证消息顺序

引言

我在《项目中为什么要使用消息队列》中列举了两个使用消息队列的例子。

(1)收银系统,确认收款成功,通过MQ通知给物流系统发货。

(2)消费积分,用户每消费一笔给用户增加一定积分,京东豆,信用卡积分,2020年如果还没倒闭的电商平台中,可以100%的确定订单系统和积分/奖励系统不是耦合在一起的。

这些都是很典型的使用消息队列的场景。

那么问题来了,想象一下,积分系统收到同一个用户同一个订单两条相同的消息会怎样?积分会被加两遍吗?针对这个问题,面试官又开始一轮三连问,你还能扛得过去吗?

这不是“面试造火箭,工作拧螺丝”,消息重复,消息积压这类问题是你入职后工作中真真切切会遇到的,不是面试官故意刁难你。

1、面试官:

那你有考虑过消息重复问题怎么解决吗?

问题分析:还是拿上面的例子分析,积分系统收到同一个用户同一个订单两条相同的消息会怎样,先不管因为什么原因消息发了两次,积分会被加两遍吗?

产品经理说: 那肯定不行呀,花100块给100个积分,积分没有买一送一服务。

订单系统RD说: 我这边没办法100%保证积分广播只发一次,万一出个bug同一笔消费积分,消息可能发了几百次也不好说。

答:产品说不行,订单RD说他不保证消息不重复,Kafka架构RD也说无法保证消息不重复,那怎么办?我是负责积分系统的,针对消息重复问题,我会针对积分累计接口做**“幂等”**设计,这个问题,首先我们应该从上游就做消息去重处理,但是我们不能100%相信上游系统一定可靠,我是消息消费端,只有我这边做了幂等设计才能完全避免这种和钱相关的bug,毕竟如果依赖上游,真的出了用户消费100元最后加了100w积分,这锅重要还是我们背。

我可以根据用户订单号或者流水号做强幂等,每成功操作一次加积分就记录下来,即使消息重负了,我只要判断同一个订单号已经操作加分了,后续我们就不会再做任何操作了。

随手写了一段伪代码给面试官:

//没收到给用户消费通知,先判断这个orderId时候已经有加过积分的历史记录,如果没有操作过,则增加。如果已经操作过,直接返回不做任何处理。
List<UserPointHistory> lists = userPointDao.queryHistory(orderId);
if(CollectionUtils.isNotEmpty(lists)){
    //1.加100分。
    userPoint.add(pointCount,orderId);
    //2.保存增加记录
      userPoint.addHistory(orderId);
}else{
    log.info("该订单已经操作过积分操作")
    return null;
}

Tip:如果幂等还不明白可以看我写的《谈谈怎么理解接口幂等设计,项目中如何保证接口幂等》,上面的代码加积分和保存增加记录要保证事务性,如果你不知道ACID千万别给自己挖坑,被面试官逮住ACID一顿问。

面试官:这个问题相对不难,有解决思路问题就不大了。

2、面试官:

在多集群消息架构中,如果消费端要求接收到的消息是有序的,怎么解决消息顺序消费问题?

问题分析:这个问题什么意思呢,比如一个消息Producer发送顺序是1 2 3,那Consumer接收到的消息也是 1 2 3 ,这就比较为难工程师了,但是还是有办法的,想要实现消息有序就要牺牲点什么东西 ---- 性能/可靠性。

答:这个问题从三个角度考虑:

Producer:让生产端同步发送消息,消息1确定发送成功后再发送消息2,不能异步,保证消息顺序入队。

服务端:Producer -> MQ Server -> Consumer 一对一关系,一对一服务,这肯定能保证消息是按照顺序消费的,那么问题来了:

  • Producer -> MQ Server -> Consumer任意一个环节出现问题,那肯定整个链路都阻塞了。
  • 单通道模型性能成为瓶颈。

topic不分区:意思就是让同一个topic主题都入一个队列,在分布式环境下如果同一个topic进入多个分区,那多个分区之间肯定无法保证消息顺序了。

Consumer:保证消费端是串行消费,禁止使用多线程。

但是这些方法都会牺牲掉系统的性能和稳定性,顺序性问题非要使用MQ来做,那也没有太好的办法了。

3、面试官:

那如何做到topic不分区,能举例说明一下吗?

问题分析:说真的,工作中要求消息顺序消费的业务场景真的挺少见的,用到的时候少,你可以不用深入研究这一块,知道方法就行,到时候真的遇到了知道从哪个方向下手。

答:用当前比较流行的RocketMQ和Kafka举例。

RocketMQ:RocketMQ提供了MessageQueueSelector队列选择机制,我们可以把 Topic 用Hash取模法,相同Topic的Hash值肯定是一样的,让同一个 Topic 同一个队列中,再使用同步发送,这样就能保证消息在一个分区有序了。

Kafka: Kafka可以把 max.in.flight.requests.per.connection 参数设置成1,这样就可以保证同一个topic在同一个分区内了。

Tip:Topic就是一个字符串,给同一类消息取个名字加以区分,如:topic.com.xxx.order.orderId,大多数用户都可以通过message key来定义,因为同一个key的message可以保证只发送到同一个partition,比如说key是user id,table row id等等。

总结

关于消息重复和消息顺序消费问题解决思路比较简单,都是一些小技巧,虽然内容比较枯燥,但是我已经尽力说得通俗易懂。

如果用两句话概括这一接的内容:

如何保证消息重复问题:消费端接口幂等。如何保证消息顺序消费问题:让同一个消息不分区,且单线程。

当然面试的时候你可别这么干巴巴两句话,那显得你太没水平了,面试最理想的效果就是无论多简单的问题你都能滔滔不绝,让面试官无话可说。

以上就是分布式面试消息队列解决消息重复保证消息顺序的详细内容,更多关于消息队列解决消息重复保证消息顺序的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

分布式面试消息队列解决消息重复保证消息顺序

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

分布式消息队列:顺序消息的基础逻辑

在分布式架构中,消息队列为实现其高性能、高可用以及弹性伸缩等特点,其存储数据的逻辑结构大都选择了多分区的模式,即将一个Topic划分为多个Partition。

解决消息队列中的关键问题:消息丢失、顺序消费、消息积压与重复消费

消息队列在分布式系统中发挥着重要作用,但同时也带来了一系列挑战。通过仔细设计和实施相应的策略,我们可以有效地解决消息丢失、顺序消费、消息积压和重复消费等问题,从而构建一个高效、可靠的分布式系统。

阿里二面:要保证消息不丢失,又不重复,消息队列怎么选型?

消息不丢失、不重复是消息队列的基本要求,但这个基本要求还是很难满足的。消息丢失这个要求,主流消息队列通过消息重试和消息持久化的方式可以满足。但消息重试也同时带来了消息重复的可能性,主流消息队列在解决重复消息的问题上并没有现成的方案,对不允许

分布式消息队列RocketMQ概念详解

RocketMQ 是阿里开源的分布式消息中间件,跟其它中间件相比,RocketMQ 的特点是纯JAVA实现,是一套提供了消息生产,存储,消费全过程API的软件系统,本文详细介绍了分布式消息队列RocketMQ概念,需要的朋友可以参考下
2023-05-19

深入理解redis分布式锁和消息队列

最近博主在看redis的时候发现了两种redis使用方式,与之前redis作为缓存不同,利用的是redis可设置key的有效时间和redis的BRPOP命令。 分布式锁 由于目前一些编程语言,如PHP等,不能在内存中使用锁,或者如Java这
2022-06-04

三分钟白话RocketMQ系列—— 如何保证消息顺序性

实现的消息的顺序性主要有两个维度,分别是「全局有序」和「局部有序」。我们围绕这两个方面来白话下消息顺序性问题。

17 个方面,综合对比 Kafka、RabbitMQ、RocketMQ、ActiveMQ 四个分布式消息队列

单个 ActiveMQ 的接收和消费消息的速度在 1 万笔/秒(持久化 一般为 1-2 万, 非持久化 2 万以上),在生产环境中部署 10 个 Activemq 就能达到 10 万笔/秒以上的性能,部署越多的 activemq broke
KafkaConsumerMQ2024-11-30

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录