RabbitMQ高阶使用队列实现

news2024/11/17 21:33:36

目录

  • 1 从打车开始说起
  • 1.1 需要解决的问题
    • 1.1.1 打车排队
  • 2 排队人数
    • 2.1 需求
      • 2.1.1 需求分析
    • 2.2 实现方案
      • 2.2.1 MySQL
        • 2.2.1.1 入队
        • 2.2.1.2 获取进度
        • 2.2.1.3 遇到问题
      • 2.2.3 Redis Zset
    • 2.3 排队人数架构介绍
    • 2.4 数据结构
      • 2.4.2 zset结构
      • 2.4.1 雪花算法
    • 2.5 功能实现
      • 2.5.1 派单
      • 2.5.2 获取排队情况
    • 2.6 演示
      • 2.6.1 派单
      • 2.6.2 排队情况查询


1 从打车开始说起

在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

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

1.1 需要解决的问题

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

在这里插入图片描述

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

1.1.1 打车排队

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

在这里插入图片描述

2 排队人数

在这里插入图片描述

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来实现排队,整体架构如下。

在这里插入图片描述

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

2.4 数据结构

2.4.2 zset结构

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

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

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

在这里插入图片描述

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

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

2.4.1 雪花算法

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

在这里插入图片描述

在这里插入图片描述
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 派单

在这里插入图片描述

2.6.2 排队情况查询

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/654771.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java 实现反转一个链表

文章目录 思路核心四步骤循环移动代码实现 思路 翻转指的是改变链表中结点的指向&#xff0c;而不是将它的数据反转。 上图展示出的就是一个反转前的链表&#xff0c;下图展示一个反转后的链表。 根据上图可以看出&#xff0c;结点的地址和数据都没有改变&#xff0c;改变的…

Java SSM框架基础面试题

一、Spring面试题 1、Spring 在ssm中起什么作用&#xff1f; Spring&#xff1a;轻量级框架作用&#xff1a;Bean工厂&#xff0c;用来管理Bean的生命周期和框架集成。两大核心&#xff1a; 1、IOC/DI(控制反转/依赖注入) &#xff1a;把dao依赖注入到service层&#xff0c;s…

Java SSM框架面试题

sql 中 ${} 和 #{}的区别&#xff1a; #将传入的参数都当成一个字符串&#xff0c;会对自动传入的数据加一个双引号。如&#xff1a;order by #{age}&#xff0c;如果传入的值是18,那么解析成sql时的值为order by “18”, 如果传入 age ,则会解析为 order by “age”将传入的参…

6.S081——Lab4——trap lab

0.briefly speaking 这是MIT 6.S081 Fall 2021课程的第四个实验&#xff0c;它是有关陷阱机制的一系列小问题&#xff0c;如果对陷阱机制仍有疑问&#xff0c;可以参考我之前写的其他3篇博客&#xff0c;它们很好地解释了一些背景知识&#xff1a; 用户态陷阱(以系统调用为例…

oracle 19c 部署

安装前的基础环境和用户配置等参考rac部署篇oracle rac部署 一、资源准备 将数据库软件上传解压到oracle的家目录(注意解压后的用户属组) [oraclerac1 ~]$ unzip -d $ORACLE_HOME xxxx.zip 二、在xmanager或者vnc中执行安装 [oraclerac1 db_1]$ ./runInstaller 先安装一个数据…

SSM 框架常见面试题

1 Spring面试题 1、Spring 在ssm中起什么作用&#xff1f; Spring&#xff1a;轻量级框架 作用&#xff1a;Bean工厂&#xff0c;用来管理Bean的生命周期和框架集成。 两大核心&#xff1a;1、IOC/DI(控制反转/依赖注入) &#xff1a;把dao依赖注入到service层&#xff0c;ser…

5.3、Dockerfile内命令

【docker】CMD ENTRYPOINT 区别 终极解读&#xff01;_绝世好阿狸的博客-CSDN博客 0、上下文路径 $ docker build -t nginx:v3 . # . 是上下文路径&#xff0c;那么什么是上下文路径呢&#xff1f; 上下文路径&#xff1a;指docker在构建镜像时想使用本机的文件&#xff0c;…

缓冲区溢出与防护

目录 一、初识缓冲区溢出 1.1 缓冲区溢出概念 1.2 缓存区 1.3 缓存区溢出的危害 1.4 缓存区溢出事件 二、缓存区溢出攻击 2.1 溢出原理 2.2 典型的寄存器 三、缓存区溢出防御 3.1 缓冲区溢出攻击目标 3.2 缓冲区溢出条件 3.3 缓冲区溢出防范 3.3.1 程序设计过程中…

【后端开发】狂神笔记:Redis进阶

文章目录 1 Redis事务1.1 Redis事务简介1.2 Redis事务操作过程1.2.1 开启事务--->执行事务1.2.2 取消事务(discurd) 1.3 事务错误1.3.1 编译期异常1.3.2 运行时异常 2 Redis实现乐观锁2.1 乐观锁和悲观锁2.2 正常执行2.3 测试异常执行 3 Jedis3.1 导入依赖3.2 编码测试3.2.1…

青翼科技自研模块化互联产品 • 模拟采集FMC子卡【产品资料】

FMC122是一款基于FMC标准规范&#xff0c;实现2路16-bit、1GSPS ADC同步采集&#xff0c;2路16-bit 2.5GSPS DAC同步回放功能子卡模块。该模块遵循VITA57.1标准&#xff0c;可直接与FPGA载卡配合使用&#xff0c;板卡ADC器件采用TI的ADS54J60芯片&#xff0c;该芯片具有两个模拟…

EasyExcel实现execl导入导出

引言 在实际开发中&#xff0c;处理 Excel 文件是一个常见的需求。EasyExcel 是一个基于 Java 的开源库&#xff0c;提供了简单易用的 API&#xff0c;可以方便地读取和写入 Excel 文件。本文将介绍如何使用 EasyExcel 实现 Excel 导入功能&#xff0c;以及一些相关的技巧和注…

java的线程池

一、线程池概念 若不使用线程池&#xff0c;在新创建的线程start()后执行完run()就自动销毁了&#xff0c;造成了资源的浪费。使用线程池可以暂时存储线程。 线程池的主要核心原理&#xff1a; 线程池的代码实现&#xff1a; 注意&#xff1a;在实际开发中线程池并不会关闭&a…

【MySQL】一文带你了解排序检索数据

&#x1f3ac; 博客主页&#xff1a;博主链接 &#x1f3a5; 本文由 M malloc 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;LeetCode刷题集&#xff01; &#x1f3c5; 欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指…

经典电路分析——看看大佬设计或代代人改进的作品——欢迎批评指正

1、TTL反相器 1&#xff09;输入0.3v a)T1&#xff0c;T2&#xff0c;T4 先分析T1的工作状态&#xff1a;计算ube1和uce1 ube1大于开启电压&#xff0c;所以ube10.7v。 因为T2&#xff0c;T4要想导通&#xff0c;V1b上需要有打通三个PN结的能力&#xff0c;也就是说V1b3*0.…

【UE 从零开始制作坦克】3-履带移动效果

目录 一、设置转向灵敏度 二、原地掉头 三、履带移动效果 效果 一、设置转向灵敏度 为了解决坦克转向灵敏度过高的问题&#xff0c;我们首先打开“TankZongLei”蓝图 选中“载具移动&#xff08;MovementComp&#xff09;&#xff08;继承&#xff09;”将转向输入率中的上…

数据结构图解--队列 的实现/算法+源码

图解--队列 最终的效果接下来 我们要做的就是 使用编程实现这种意识形态下的结构创建队列结构体初始化init进队入队 尾部插入队列的判断满操作出队队列是否为空遍历队列代码的操作交互意识 最终的效果 1.队列的结构形式 队列是一种线性结构 但是特殊的线性结构 只要的特殊在于…

【炫酷登录界面】详解5款高级的前端登录页面及实现源码(附完整源码)

【写在前面】 其实好早之前我就想写这篇文章了&#xff0c;也有些网友还会私信我&#xff0c;说有时候公司要求登录页面的改造&#xff0c;问我能不能出一期关于登录页的文章&#xff0c;于是乎我也是拖到这个时候才整理出来&#xff0c;其实每篇文章的效果内容我都是自己亲自去…

基于51单片机设计的花样流水灯设计

一、项目介绍 花样流水灯是一种常见的LED灯效果,被广泛应用于舞台表演、节日庆典、晚会演出等场合。在现代智能家居、电子产品中,花样流水灯也被广泛使用,通过调整亮灭顺序和时间,可以实现各种炫酷的灯光效果,增强用户体验。而51单片机作为一种常见的嵌入式开发平台,具有…

深搜-剪枝优化

目录 1.问题引入 2.知识讲解 【搜索术语】 &#xff08;1&#xff09; *可行性剪枝*&#xff1a; &#xff08;2&#xff09; *预处理剪枝*&#xff1a; &#xff08;3&#xff09; *重复性剪枝*&#xff1a; &#xff08;4&#xff09; *最优性剪枝*&#xff1a; &…

动态规划IV (118、119、198、213、337)

CP118 杨辉三角 题目描述&#xff1a; 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 学习记录&#xff1a; 思想就是没有思想&#xff0c;的杨辉三角&#xff0c;但是注意resiz…