优惠券秒杀7——Redis消息队列实现异步秒杀
一、问题引出——
内存溢出——
之前我们使用的是JDK里面的阻塞队列,而这个队列使用的是JDK里面的内存。如果不加以阻止,在高并发情况下可能会有无数订单对象需要创建并且放到阻塞队列里面。可能会导致将来内存溢出。
数据安全问题——
之前的服务是基于JVM内存保存的,没有持久化机制
情况一:”如果服务突然宕机了,那内存里的所有的订单信息都丢失了。用户已经付款,但是后台没有收到相关信息,出现不一致的情况。
情况二:当我们从队列里面取出订单后,在正准备执行之时,出现了异常。等回复后原本取出的订单已经不复存在了。也相当于订单丢失了。
补充一点——JVM、JRE、JDK
二、解决方案——消息队列MQ(Message Queue)
上面的两个问题在消息队列中均不存在,均可以规避。
市面上有关MQ的专业中间件有rabbitMQ、rocketMQ、kafka等,完整的消息队列MQ只是请点击这里。
下面是MQ的相关介绍——
但是市面上的MQ太大了,对于小公司,Redis里面提供了低成本的实现消息队列的组件及方法足以使用。
本节使用Redis来完成搭建——
三、基于List结构模拟消息队列
使用BRPOP或者BLPOP来实现阻塞效果
优点——
缺点——
四、基于Pubsub的消息队列
基于Pubsub实现多消费者
优点——
缺点——
五、基于Stream的消息队列
stream是Redis里面最全面的消息队列
(一)XADD、XLEN——建立、查看消息队列
(二)读取消息的方式之一:XREAD
在Java中的使用——
XREAD命令特点——
XREAD读取缺点——漏读消息
(三)基于stream的消息队列-消费者组
基本命令——创建、删除消费者组
基本命令——从消费者组读取消息
基本命令——确认消息ACK
基本命令——获取XPENDING里面的消息
处理消息的流程——
正常情况下,先用">“号的方式获取所有未消费的消息。拿到以后就处理处理完了以后就确认。
在确认的过程中,如果出现了异常,消息就会进入pending—List。
在Java代码中体现出就是将异常catch,catch到了以后就将最后的ID从”>"号改为0,这样就不是取未消费消息了,而是取所有出现异常的消息在pending list里的消息,这个时候将pending list里面的消息拿出来,处理掉就清空。
处理完成后,我们给他确认掉pending list是不是清空。
之后再回头将取消息命令改成“>”, 去获取所有未消费消息,就回归正常了
在Java中中的体现——
(四)总结——STREAM类型MQ的XREADGROUP命令特点——
六、Redis的三种消息队列的对比——
七、基于Steam的异步秒杀机制
由于在企业中使用rabbitMQ多,这里实现移步微服务中的rabbitMQ.