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

目录
  • 引言
  • 1、面试官:
    • 那你有考虑过消息重复问题怎么解决吗?
  • 2、面试官:
    • 在多集群消息架构中,如果消费端要求接收到的消息是有序的,怎么解决消息顺序消费问题?
  • 3、面试官:
    • 那如何做到topic不分区,能举例说明一下吗?
  • 总结

引言

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

(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等等。

总结

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

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

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

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

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

(0)

相关推荐

  • Java面试题冲刺第十六天--消息队列

    目录 面试题1:说说你对消息队列的理解,消息队列为了解决什么问题? 解耦 异步 削峰 追问1:消息队列有什么优缺点 面试题2:对于消息中间机,你们是怎么做技术选型的? 面试题3:如何确保消息正确地发送至 RabbitMQ?如何确保消息接收方消费了消息? 发送方确认模式 接收方确认机制 追问1:如何保证MQ消息的可靠传输? 总结 面试题1:说说你对消息队列的理解,消息队列为了解决什么问题? 我们公司业务系统一开始体量较小,很多组件都是单机版就足够,后来随着用户量逐渐扩大,我们程序也采用了微服务的设

  • 浅谈Java消息队列总结篇(ActiveMQ、RabbitMQ、ZeroMQ、Kafka)

    一.消息队列概述 消息队列中间件是分布式系统中重要的组件,主要解决应用解耦,异步消息,流量削锋等问题,实现高性能,高可用,可伸缩和最终一致性架构.目前使用较多的消息队列有ActiveMQ,RabbitMQ,ZeroMQ,Kafka,MetaMQ,RocketMQ. 二.消息队列应用场景 以下介绍消息队列在实际应用中常用的使用场景.异步处理,应用解耦,流量削锋和消息通讯四个场景. 2.1异步处理 场景说明:用户注册后,需要发注册邮件和注册短信.传统的做法有两种 1.串行的方式;2.并行方式 a.串

  • 解决kafka消息堆积及分区不均匀的问题

    目录 kafka消息堆积及分区不均匀的解决 1.先在kafka消息中创建 2.添加配置文件application.properties 3.创建kafka工厂 4.展示kafka消费者 kafka出现若干分区不消费的现象 定位过程 验证 解决方法 kafka消息堆积及分区不均匀的解决 我在环境中发现代码里面的kafka有所延迟,查看kafka消息发现堆积严重,经过检查发现是kafka消息分区不均匀造成的,消费速度过慢.这里由自己在虚拟机上演示相关问题,给大家提供相应问题的参考思路. 这篇文章有点

  • java开发微服务架构设计消息队列的水有多深

    目录 消息队列的作用 消息队列的设计难题 处理并发和顺序消息 处理重复消息 编写幂等消息处理器 跟踪消息并丢弃重复消息 处理事务性消息 使用数据库表作为消息队列 使用事务日志发布事件 RocketMQ事务消息解决方案 很多人在做架构设计时往往会"过度设计",简单问题复杂化,上来就引一堆中间件,我想大概原因主要有下面两点: 为了秀(学)技术而架构 我们常说技术是为业务服务的,不能为了技术而技术,为了秀技术引入一堆复杂架构这是要不得的. 考虑问题不全面,或者说广度不够,不知道如何简单化 举

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

    目录 引言 1.面试官: 那你有考虑过消息重复问题怎么解决吗? 2.面试官: 在多集群消息架构中,如果消费端要求接收到的消息是有序的,怎么解决消息顺序消费问题? 3.面试官: 那如何做到topic不分区,能举例说明一下吗? 总结 引言 我在<项目中为什么要使用消息队列>中列举了两个使用消息队列的例子. (1)收银系统,确认收款成功,通过MQ通知给物流系统发货. (2)消费积分,用户每消费一笔给用户增加一定积分,京东豆,信用卡积分,2020年如果还没倒闭的电商平台中,可以100%的确定订单系统和

  • WCF分布式开发之MSMQ消息队列

    目录 一.MSMQ简介 1.MSMQ的实现原理 2.安装 3.两个概念 4.MicroSoft.Message.Queue常用的方法: 二.服务端 三.客户端 一.MSMQ简介 MSMQ(微软消息队列)是Windows操作系统中消息应用程序的基础,是用于创建分布式.松散连接的消息通讯应用程序的开发工具. MSMQ与XML Web Services和.Net Remoting一样,是一种分布式开发技术.但是在使用XML Web Services或.Net Remoting组件时,Client端需要

  • Redis 使用 List 实现消息队列的优缺点

    目录 什么是消息队列 消息队列满足哪些特性 消息有序性 重复消息处理 可靠性 List 实现消息队列 LPUSH RPOP 实时消费问题 重复消费 消息可靠性 需要注意的是 Redission 实战 添加依赖 Java 代码实战 单元测试 总结 需要注意的是,我们要避免生产者过快,消费者过慢导致的消息堆积占用 Redis 的内存. 分布式系统中必备的一个中间件就是消息队列,通过消息队列我们能对服务间进行异步解耦.流量消峰.实现最终一致性. 目前市面上已经有 RabbitMQ.RochetMQ.A

  • Golang中优秀的消息队列NSQ基础安装及使用详解

    前言 NSQ是Go语言编写的,开源的分布式消息队列中间件,其设计的目的是用来大规模地处理每天数以十亿计级别的消息.NSQ 具有分布式和去中心化拓扑结构,该结构具有无单点故障.故障容错.高可用性以及能够保证消息的可靠传递的特征,是一个成熟的.已在大规模生成环境下应用的产品. 背景介绍 在服务器最开始的时候,基本上在一台主机上就能解决大部分问题,所以一般架构设计如下: 但是,突然某一天,来了一个新需求,我们服务器上不只是简单的储存一些文本信息,我们需要储存图片甚至视频,显然直接在一台主机上再部署一个

  • 大数据Kafka:消息队列和Kafka基本介绍

    目录 一.什么是消息队列 二.消息队列的应用场景 异步处理 应用耦合 限流削峰 消息驱动系统 三.消息队列的两种方式 点对点模式 发布/订阅模式 四.常见的消息队列的产品 1) RabbitMQ 2) activeMQ: 3) RocketMQ 4) kafka 五.Kafka的基本介绍 一.什么是消息队列 消息队列,英文名:Message Queue,经常缩写为MQ.从字面上来理解,消息队列是一种用来存储消息的队列 .来看一下下面的代码 上述代码,创建了一个队列,先往队列中添加了一个消息,然后

  • SpringBoot整合rockerMQ消息队列详解

    目录 Springboot整合RockerMQ 使用总结 消费模式 生产者组和消费者组 生产者投递消息的三种方式 如何保证消息不丢失 顺序消息 分布式事务 Springboot整合RockerMQ 1.maven依赖 <dependencies> <!-- springboot-web组件 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>

  • 学习spring事务与消息队列

    在开发过程中,遇到一个bug,产生bug的原因是spring事务提交晚于消息队列的生产消息,导致消息队列消费消息时获取到的数据不正确.这篇文章介绍问题的产生和一步步的解决过程. 一.问题的产生: 场景还原:接口中的一个方法,首先修改订单状态,然后向消息队列中生产消息,消息队列的消费者获取到消息检测订单状态,发现订单状态未更改. 代码: @Service(orderApi) public class OrderApiImpl implements OrderApi { @Resource MqSe

  • PHP消息队列实现及应用详解【队列处理订单系统和配送系统】

    本文实例讲述了PHP消息队列实现及应用.分享给大家供大家参考,具体如下: 在互联网项目开发者经常会遇到『给用户群发短信』.『订单系统有大量的日志需要记录』或者在秒杀业务的时候服务器无法承受瞬间并发的压力. 这种情况下,我们怎么保证系统正常有效的运行呢? 这个时候,我们可以引入一个叫『消息队列』的概念来解决上面的需求. 消息队列的概念.原理和场景 在高并发的时候,程序往往无法做到及时的处理.我们引入一个中间的系统,来进行分流和减压. 所以从本质上讲:消息队列就是一个队列结构的中间件.也就是说,你把

  • kafka 消息队列中点对点与发布订阅的区别说明

    目录 背景知识 1.JMS中定义 2.二者分析与区别 2.1 点对点模式 2.2 发布订阅模式 3.流行的消息队列模型比较 3.1 RabbitMQ 3.2 Kafka 背景知识 JMS一个在 Java标准化组织(JCP)内开发的标准(代号JSR 914).2001年6月25日,Java消息服务发布JMS 1.0.2b,2002年3月18日Java消息服务发布 1.1. Java消息服务(Java Message Service,JMS)应用程序接口是一个Java平台中关于面向消息中间件(MOM

随机推荐