ActiveMq的顺序性消费问题

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 首先说下顺序性消费带来的问题,都不考虑链式调用业务,就单纯互斥操作的业务,单机mq,单机redis环境,在mq消息等待被消费时的顺序问题

欢迎订阅关注公众号:赵KK日常技术记录
首先说下顺序性消费带来的问题,都不考虑链式调用业务,就单纯互斥操作的业务,单机mq,单机redis环境,在mq消息等待被消费时,A消息进入队列等待被消费,B消息进入队列,此时A消息未消费完毕,B要根据A消息的结果进行操作,目前发生的问题就是多线程并发调用时,mq消费并没有按着先进先出的顺序进行消费,在同一时刻库里存在相同数据,但这是不允许的,在此期间如果其他人去查看数据,如果来自数据库,那必定是不准确的。所以部分业务查的redis,但更坏的情况,此时redis凉了怎么办?

业务的ABA问题

业务1将数据A从缓存中取到,业务B将数据A从缓存中取到并将A变成了B,然后又将B变成了A,业务1发现此时数据仍是A,A操作成功,尽管业务操作时成功的,但不代表整个过程就没问题。另外,虽然顺序性问题有可能带来的结果是一致的,但是不代表这个过程中影响的其他数据就没问题。
image.png

如图,同一时刻库中存入相同数据6条,但严谨逻辑只能允许库中存在相同数据只有一条,如果此时其他业务查询相关数据,必定会出现多结果返回

设想解决方案一:原子计数

 方案:在每条数据进行操作之前,先判断两次操作数据是否为同一个,即redis的kv为同一个,如果相同则此时对key进行标记incr,步进1,在mq进行消费时,从redis中取出此key的步进值与传进来的步进值比较,按理说只需要记录想用kv值得最后最大步进值得操作
 Long incr = redisService.incr(key,1);
 Object o = redisService.getIncrValue("key");
 if(o.toString().equals(vo.getIncr())){
       //业务逻辑     
 }

结果测试:同样会出现此问题。一开始想到当前页面为同一用户对同一信息的操作,不会出现或者点不出如此高的并发,那不考虑接口被恶意攻击的情况,使用jemeter进行动态传参结果如何呢?
image.png

每次的参数入参读取文件值,使每次结果为不同的操作,或者两台机器为同一账户对同一信息进行操作,必定会产生网络延迟造成对结果不一致的问题。

设想解决方案二:分布式锁

方案:对当前操作进行加锁,并保证同一值得锁操作为同一把锁时进行业务处理,集群模式下对消息进行分组,具体方案不成熟,引入redisson处理,但也疑问为了保证顺序性问题引入分布式锁的成本与性能问题,最终没能达到理想结果。

public Boolean tryLock(String lockKey, TimeUnit unit, int waitTime, int leaseTime) {
        RLock lock = redissonClient.getLock(lockKey);
        try {
            return lock.tryLock(waitTime,unit);
        } catch (Exception e) {
           return  false;
        }
    }
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
9月前
|
消息中间件 存储 缓存
RabbitMq如何防止消息被重复消费
RabbitMq如何防止消息被重复消费
970 0
|
消息中间件 存储 监控
ActiveMQ系列: ActiveMQ 的死信队列与消费重试机制
maximumRedeliveryDelay:最大传送延迟,只在 useExponentialBackOff 为 true 时有效(V5.5),假设首次重连间隔为 10ms,倍数为 2,那么第二次重连时间间隔为 20ms,第三次重连时间间隔为 40ms,当重连时间间隔大的最大重连时间间隔时,以后每次重连时间间隔都为最大重连时间间隔。默认为 -1。
795 0
ActiveMQ系列: ActiveMQ 的死信队列与消费重试机制
|
4月前
|
消息中间件 缓存 监控
mq如何保证消息顺序性
mq如何保证消息顺序性
49 0
|
5月前
|
消息中间件 算法 Kafka
Kafka 如何保证消息消费的全局顺序性
Kafka 如何保证消息消费的全局顺序性
|
8月前
|
消息中间件 关系型数据库 MySQL
如何保证MQ中消息的顺序性?
如何保证MQ中消息的顺序性?
75 1
|
9月前
|
消息中间件 存储
RabbitMQ如何保证消息发送成功
RabbitMQ如何保证消息发送成功
92 0
RabbitMQ如何保证消息发送成功
|
10月前
|
消息中间件
RabbitMQ 如何保证消息的顺序性
RabbitMQ 如何保证消息的顺序性
174 0
|
10月前
|
消息中间件 调度
RabbitMQ如何保证消费的顺序性
RabbitMQ如何保证消费的顺序性
2637 0
|
10月前
|
消息中间件 分布式计算 Kafka
Kafka如何保证消费的顺序性 ?
Kafka 通过以下机制来保证消费的顺序性
2459 0
|
12月前
|
消息中间件 存储 负载均衡
RocketMQ 顺序消费机制
顺序消息是指对于一个指定的 Topic ,消息严格按照先进先出(FIFO)的原则进行消息发布和消费,即先发布的消息先消费,后发布的消息后消费。 顺序消息分为**分区顺序消息**和**全局顺序消息**。
3151 1
RocketMQ 顺序消费机制