RabbitMQ高阶使用队列实现

这篇具有很好参考价值的文章主要介绍了RabbitMQ高阶使用队列实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


1 从打车开始说起

RabbitMQ高阶使用队列实现

RabbitMQ高阶使用队列实现

我们把滴滴打车的流程简化下

RabbitMQ高阶使用队列实现

  1. 登录app后点击打车开始进行打车
  2. 打车服务开始为司机派单
  3. 司机接单后开始给来接驾
  4. 上车乘客后处于行程中
  5. 行程结束后完成本次打车服务

1.1 需要解决的问题

我们需要实现派单服务,用户发送打车订单后需要进行进行派单,如果在指定时间内没有找到司机就会收到派单超时的通知,并且能够实时查看当前排队的抢单人数

RabbitMQ高阶使用队列实现

下面我们来介绍下涉打车涉及到的一些问题

1.1.1 打车排队

主要讲解打车服务在超时后的处理,比如打车后等待多长时间没有打到车后会通知等待超时

RabbitMQ高阶使用队列实现

2 排队人数

RabbitMQ高阶使用队列实现

2.1 需求

在打车的过程中如果人数较多的情况下会在派单中等待,如果想知道我的前面还有多少人呢,我们就需要一个排队人数的功能

​ 接受用户的派单数据,但因为派单处理需要一定的时间,所以只能在MQ中有序消费数据,对用户进行排队操作,当然这个排队操作,用户是不透明的,某些用户的请求可能被优先处理,但是通过MQ可以实现整体的有序。

​ 用户很关心自己派单目前的处理进度,即和我一样打车的前面还有多少人,打车APP上显示“你前面还有多少人在排队”,所以后台要能告知用户目前他的派单进度。

2.1.1 需求分析

  • 入队:可以理解为写操作,需要后端存储数据。
  • 获取进度:可以理解为读操作,而且可以预见这个读操作应该比写操作频繁,如果用户很关注她的订单进展,说不定会一直刷新查看他的订单排队情况。

2.2 实现方案

2.2.1 MySQL

​ 用户的订单数据肯定得持久化存储,MySQL是一个不错的选择,既然需求这么简单,无非一个订单数据嘛,暂且用一张表“订单表(T_Order)”来保存正在排队的订单,已经处理完毕的订单则从T_Order表迁移至“(历史订单表T_History_Order)”,这样的好处避免订单表数据量太大,提高读写性能。

2.2.1.1 入队

完成订单的入库,显然就是一个insert语句了

insert into T_Order(...) values(...);
2.2.1.2 获取进度

需查询自己订单的排队情况,那肯定看比自己订单时间还早的用户有多少人了,这些比自己下单时间还早的人,就是排在自己前面的人了,假设一个用户同时只能有一个订单在排队

#先查出自己订单时间, 假设是1429389316
select orderTime from T_Order where uid=8888;

#再查有多少人的订单时间比自己的早
select count(orderTime) from T_Order where orderTime <= 1429389316;
2.2.1.3 遇到问题

互联网的精髓就是“小步快跑,快速迭代”,用MySQL快速完成需求,面向用户服务后

​ 初期阶段,一切ok,但是当这个业务运营得好,用户量大的时候,就会发现用户经常投诉“我查询自己的订单排队进度,经常报错”,甚至处理订单的同事,也经常抱怨从订单系统里面查看订单,非常缓慢,select count 操作基本都是全表扫描操作,看来MySQL面对这么大规模的全表查询操作,还是有点吃力。

2.2.3 Redis Zset

NoSQL在互联网领域的江湖地位已经很牢靠了,看来得请他老人家出来救场了

​ 没错,使用Redis的有序集合(sorted sets)数据结构,就可以完美的解决这个问题,因为有序集合底层的实现是跳表这种数据结构,时间复杂度是logN,即使有序集合里面的订单有100万之多,耗时也基本都是纳秒级别(基本不到1毫秒)

  1. 用户提交一个订单,我们写入redis的zset中。
  2. 用户要查询自己的订单排队情况,这时候我们只要查询redis的有序集合就可以了,命令为rank
  3. 当这个订单被处理完成后,直接一个zrem命令将订单从有序集合中删除即可

因为Redis基本都是内存操作,而且有序集合的底层实现是跳表这种效率媲美平衡树,但是实现又简单的数据结构,从而完美的释放了MySQL的读压力。

2.3 排队人数架构介绍

​ 打车如果出现排队我们需要能够对当前排队的人数进行预估,能够知道当前我们前面有多少人在排队,我们采用redis的zset来实现排队,整体架构如下。

RabbitMQ高阶使用队列实现

  1. 用户打车通过zset加入到redis的有序集合
  2. 异步将数据推送到RabbitMQ延迟以及进行正常业务处理
  3. 处理完成后在zset中删除元素
  4. 用户查询人数通过Rank命令进行查询

2.4 数据结构

2.4.2 zset结构

Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。

​ 不同的是每个元素都会关联一个 double 类型的分数,redis 正是通过分数来为集合中的成员进行从小到大的排序。

​ 我们只需要使用rank命令统计从0-当前key对应的分数的key的数量就可以得到当前的排名了

RabbitMQ高阶使用队列实现

​ 因为Redis基本都是内存操作,而且有序集合的底层实现是跳表这种效率媲美平衡树,但是实现又简单的数据结构,从而完美的释放了MySQL的读压力。

我们如何来保证分数不重复,并且是有序递增的呢,这里就要祭出来我们的雪花算法

2.4.1 雪花算法

SnowFlake算法生成id的结果是一个64bit大小的整数,它的结构如下图:

RabbitMQ高阶使用队列实现

RabbitMQ高阶使用队列实现
4095个数字,来表示同一机器同一时间截(毫秒)内产生的4095个ID序号。

由于在Java中64bit的整数是long类型,所以在Java中SnowFlake算法生成的id就是long来存储的。

SnowFlake可以保证

  1. 所有生成的id按时间趋势递增
  2. 整个分布式系统内不会产生重复id(因为有datacenterId和workerId来做区分)

2.5 功能实现

2.5.1 派单

使用redisTemplate操作zset将username以及workid压入zset中

redisTemplate.opsForZSet().add(TaxiConstant.TAXT_LINE_UP_KEY, taxiBO.getUsername(), taxiBO.getId());

2.5.2 获取排队情况

使用redisTemplate操作zset获取username对应的排名

redisTemplate.opsForZSet().rank(TaxiConstant.TAXT_LINE_UP_KEY, username);

2.6 演示

2.6.1 派单

RabbitMQ高阶使用队列实现

2.6.2 排队情况查询

RabbitMQ高阶使用队列实现文章来源地址https://www.toymoban.com/news/detail-487154.html

到了这里,关于RabbitMQ高阶使用队列实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 消息队列中间件,RabbitMQ的使用,死信队列,延迟队列,利用枚举实现队列,交换机,RountKey的声明

    目录 0.交换机种类和区别 1.声明队列和交换机以及RountKey 2.初始化循环绑定 3.声明交换机 4.监听队列 4.1 监听普通队列 4.2监听死信队列  5.削峰填谷的实现 Direct Exchange(直连交换机) : 直连交换机将消息发送到与消息的路由键完全匹配的队列。它是最简单的交换机类型之一。

    2024年04月23日
    浏览(134)
  • RabbitMQ高阶使用消息推送

    我们把滴滴打车的流程简化下 登录app后点击打车开始进行打车 打车服务开始为司机派单 司机接单后开始给来接驾 上车乘客后处于行程中 行程结束后完成本次打车服务 我们需要实现派单服务,用户发送打车订单后需要进行进行派单,如果在指定时间内没有找到司机就会收到

    2024年02月15日
    浏览(34)
  • RabbitMQ高阶使用延时任务

    我们把滴滴打车的流程简化下 登录app后点击打车开始进行打车 打车服务开始为司机派单 司机接单后开始给来接驾 上车乘客后处于行程中 行程结束后完成本次打车服务 我们需要实现派单服务,用户发送打车订单后需要进行进行派单,如果在指定时间内没有找到司机就会收到

    2024年02月11日
    浏览(24)
  • Java中如何使用消息队列实现异步(ActiveMQ,RabbitMQ,Kafka)

    在 Java 中,可以使用消息队列实现异步处理。下面是一个简单的示例代码,用于说明如何使用 ActiveMQ 实现消息队列异步处理: 添加 ActiveMQ 依赖 在 pom.xml 文件中添加以下依赖: 创建消息队列 创建一个名为 “TestQueue” 的消息队列,并配置 ActiveMQ 连接信息: 创建消息消费者

    2024年02月16日
    浏览(55)
  • 消息队列-RabbitMQ:延迟队列、rabbitmq 插件方式实现延迟队列、整合SpringBoot

    1、延迟队列概念 延时队列内部是有序的 , 最重要的特性 就体现在它的 延时属性 上,延时队列中的元素是希望在指定时间到了以后或之前取出和处理,简单来说, 延时队列就是用来存放需要在指定时间被处理的元素的队列。 延迟队列使用场景: 订单在十分钟之内未支付则

    2024年02月22日
    浏览(52)
  • Rabbitmq死信队列及延时队列实现

    问题:什么是延迟队列 我们常说的延迟队列是指消息进入队列后不会被立即消费,只有达到指定时间后才能被消费。 但RabbitMq中并 没有提供延迟队列功能 。那么RabbitMQ如何实现延迟队列 通过:死信队列 + RabbitMQ的TTL特性实现。 实现原理 给一个普通带有过期功能的队列绑定一

    2024年02月15日
    浏览(47)
  • SpringBoot实现RabbitMQ的简单队列(SpringAMQP 实现简单队列)

    SpringAMQP 是基于 RabbitMQ 封装的一套模板,并且还利用 SpringBoot 对其实现了自动装配,使用起来非常方便。 SpringAmqp 的官方地址:https://spring.io/projects/spring-amqp 说明 : 1.Spring AMQP 是对 Spring 基于 AMQP 的消息收发解决方案,它是一个抽象层,不依赖于特定的 AMQP Broker 实现和客户端

    2024年04月13日
    浏览(39)
  • RabbitMQ之TTL+死信队列实现延迟队列

    RabbitMQ是一个流行的消息队列系统,它提供了许多有用的功能,其中之一是TTL(Time To Live)和死信队列。这些功能可以用来实现延迟队列,让我们来看看如何使用它们。 首先,什么是TTL?TTL是消息的存活时间,它可以设置为一个特定的时间段。如果消息在这个时间段内没有被

    2024年02月13日
    浏览(45)
  • RabbitMQ系列(18)--RabbitMQ基于插件实现延迟队列

    1、前往RabbitMQ官网下载往RabbitMQ添加延迟消息的插件 RabbitMQ官网下载插件的网址:https://www.rabbitmq.com/community-plugins.html 2、下载rabbitmq_delayer_message_exchange插件(注:RabbitMQ是什么版本的,下载的插件就得是什么版本的,得对应上,以下截图为官方文档的对插件版本的要求说明)

    2024年02月16日
    浏览(39)
  • RabbitMQ实现延迟消息的方式-死信队列、延迟队列和惰性队列

    当一条消息因为一些原因无法被成功消费,那么这这条消息就叫做死信,如果包含死信的队列配置了dead-letter-exchange属性指定了一个交换机,队列中的死信都会投递到这个交换机内,这个交换机就叫死信交换机,死信交换机再绑定一个队列,死信最终会进入到这个存放死信的

    2024年02月19日
    浏览(55)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包