前言
在我们日常生活中,我们可以发现:
在淘宝、京东等购物平台上下单,超过一定时间未付款,订单会自动取消。
打车的时候,在规定时间没有车主接单,平台会取消你的单并提醒你暂时没有车主接单。
点外卖的时候,如果商家在10分钟还没接单,就会自动取消订单。
收快递的时候,如果我们没有点确认收货,在一段时间后程序会自动完成订单。
在平台完成订单后,如果我们没有在规定时间评论商品,会自动默认买家不评论。
…
这时,我们可以想想为什么要这样做?
因为这样可以保证商品的库存可以释放给其他人购买,你可以不用一直等待打车却得不到回复,你可以及时换一家店点到外卖。
如何实现
这时我们可以看看这个图,来看看消息延迟是如何处理的
当用户发送一个消息请求给服务器后台的时候,服务器会检测这条消息是否需要进行延时处理,如果需要就放入到延时队列中,由延时任务检测器进行检测和处理,对于不需要进行延时处理的任务,服务器会立马对消息进行处理,并把处理后的结果返会给用户。
对于在延时任务检测器内部的话,有查询延迟任务和执行延时任务两个职能,任务检测器会先去延时任务队列进行队列中信息读取,判断当前队列中哪些任务已经时间到期并将已经到期的任务输出执行(设置一个定时任务)。
这时,我们可以想一想在Redis的数据结构中有哪些能进行时间设置标志的命令?
是不是想到的 zset 这个命令,具有去重有序(分数排序)的功能。没错,你想对了
我们可以使用 zset(sortedset)这个命令,用设置好的时间戳作为score进行排序,使用 zadd score1 value1 …命令就可以一直往内存中生产消息。
再利用 zrangebysocre 查询符合条件的所有待处理的任务,通过循环执行队列任务即可。也可以通过 zrangebyscore key min max withscores limit 0 1 查询最早的一条任务,来进行消费
总的来说,你可以通过以下两种方式来实现:
- 使用zrangebyscore来查询当前延时队列中所有任务,找出所有需要进行处理的延时任务,在依次进行操作。
- 查找当前最早的一条任务,通过score值来判断任务执行的时候是否大于了当前系统的时候,比如说:最早的任务执行时间在3点,系统时间在2点58分),表示这个应该需要立马被执行啦,时间快到了。
写在最后
我们可以想一想Redis来实现延时队列有何优势呢?
其实,Redis用来进行实现延时队列是具有这些优势的:
- Redis zset支持高性能的 score 排序。
- Redis是在内存上进行操作的,速度非常快。
- Redis可以搭建集群,当消息很多时候,我们可以用集群来提高消息处理的速度,提高可用性。
- Redis具有持久化机制,当出现故障的时候,可以通过AOF和RDB方式来对数据进行恢复,保证了数据的可靠性
如此之外,当然还有消息中间件rabbmitMQ, Kafka, Netty等都可以实现延迟队列的作用,有兴趣的可以深入研究哦!
如果可以帮到你,记得关注我哦_