实现任务队列之前,我们先了解一下使用任务队列有哪些好处:
1. 松耦合。生产者和消费者无需知道彼此的实现细节,只需要约定好任务的描述格式。这使得生产者和消费者可以由不同的团队使用不同的编程语言编写。
2. 易于扩展。消费者可以由多个,而且可以分布在不同的服务器中,借此可以轻易地降低单台服务器的负载。
要实现队列很自然就想到Redis的列表类型,以及LPUSH和RPOP命令。如果要实现任务队列,只需要让生产者将任务使用LPUSH命令加入到某个键中,另一边让消费者不断的使用RPOP命令从该键中取出任务即可。Redis的伪代码实现如下:
# 无限循环读取任务队列中的内容 loop $task = RPOP queue if $task # 如果任务队列中有任务,则执行它 execute($task) else # 如果没有任务,则等待1秒,以免过于频繁的请求数据 wait 1 second
至此,一个使用Redis实现的简单任务队列就写好了,不过还有一点问题:当任务队列中没有任务时,消费者每秒都会调用一次RPOP命令查看是否有新任务。
优化:借助BRPOP命令,可以实现一旦有新任务加入队列就通知消费者
BRPOP命令接收两个参数,第一个是键名,第二个是超时时间,单位是秒。当超过了此时间仍然没有获得新元素的话就会返回nil。 如果超时时间设为“0”,表示不限制等待的时间,如果没有新元素加入列表就会永远阻塞下去。
BRPOP 和 RPOP命令相似,唯一区别是:任务列表中没有元素时BRPOP命令会一直阻塞住连接,直到有新元素加入。上面的伪代码可以优化为:
loop # 如果任务队列中没有新任务,BRPOP命令会一直阻塞,不会执行execute() $task = BRPOP queue, 0 # 返回值是一个数组,数组的第二个元素是我们需要的任务 execute($task[1])
队列有的时候需要优先级。比如:系统需要发送确认邮件和通知邮件两种任务同时存在时,应该优先执行确认邮件。具体场景如下,订阅一个名人的博客的用户有10万人,当该博客发布一篇新文章后,博客就会向任务队列中添加10万个发送通知邮件的任务。如果每一封邮件需要10ms,那么全部完成这10万个任务就需要:100 000 * 10 / 1000=1000秒(将近20分钟)。加入这期间有新用户想订阅该博客,当提交完自己的邮箱并看到网页提示查收确认邮件时,该用户并不知道向自己发送的确认邮件的任务被加入到已经有10万个任务的队列中,需要为此等待近20分钟。
分析具体场景,发布新文章后通知订阅用户的任务并不很紧急,延迟20分钟完全可以接受。所以可以得出如下结论:当发送确认邮件和发送通知邮件两种任务同时存在时,应该优先执行前者。为了实现这一目的,我们需要实现一个优先级队列。
BRPOP命令可以同时接受多个键,其完整的命令格式为:BRPOP key [key ...] timeout, 如:BRPOP queue1 queue2 0.着意味着同时检测多个键,如果其中有一个键有元素,则从该键中弹出元素;如果多个键都有元素,则按照从左到右的顺序取第一个键中的第一个元素。
借此特性可以实现区分优先级的任务队列。我们分别使用queue:confirmation.email 和 queue.notification.email 两个键存储发送确认邮件和发送通知邮件两种任务,然后将消费者的伪代码修改为:
loop $task = BRPOP queue:confirmationl.email, queue:notification.email, 0 execute($task[1])
这时,一旦发送确认邮件的任务被加入到queue.confirmation.email队列中,无论queue:notification.email还有多少任务,消费者都会优先完成发送确认邮件的通知任务。
相关推荐
利用Redis来实现延迟队列的主要思路是借助Redis的Sorted Set数据类型来实现。 具体做法是将任务的执行时间作为分数(score),任务的内容作为值(value),将任务按照执行时间排序存储在有序集合中。然后周期性地...
用Redis实现分布式锁 与 实现任务队列
为了实现类似的需求,Web项目中一般的实现方法是使用消息队列(Message Queue),比如MemcacheQ,RabbitMQ等等,都是很著名的产品。 消息队列说白了就是一个最简单的先进先出队列,队列的一个成员就是一段文本。正是...
redis实现消息队列步骤如下: 1).redis函数rpush,lpop 2).建议定时任务入队列 3)创建定时任务出队列 文件:demo.php插入数据到redis队列 <?php $redis = new Redis(); $redis->connect('127.0.0.1',6379); $...
redis实现延迟消息队列 需求背景 最近在做一个排队取号的系统 在用户预约时间到达前XX分钟发短信通知 在用户预约时间结束时要判断用户是否去取号了,不然就记录为爽约 在用户取号后开始,等待XX分钟后要发短信...
基于Redis实现的分布式队列,队列任务监控,任务超时、失败任务重试等特性
BBBUG聊天室API端,基于Thinkphp6实现API部分,命令行运行后台歌曲下载与同步任务,Redis做歌曲队列缓存。特色功能(创建房间、切换房间,房间权限与房间类型管理。点歌/切歌/听歌与歌曲播放进度同步。聊天、送歌等...
一、前言 双十一刚过不久,大家都知道在天猫、京东、苏宁等等电商网站上有很多秒杀活动,例如在某一个时刻抢购一个原价1999现在秒杀价只要999的手机时,会迎来一个用户请求的高峰期,可能会有几十万几百万的并发量...
Redis设计与实现经典实用教程,全面介绍管道、事务、持久化和复制等技术。深度揭秘Redis的存储结构,剖析Redis空间优化方法。...使用Redis实现任务队列。领略Redis脚本的魅力,了解脚本的细节和技巧
然后定时从任务队列里中取出任务调用第三方 API,若返回状态为”异步处理中“,将该任务再次加入任务队列,若返回状态为”已处理完毕“,将返回数据入库。 根据以上问题,想到使用 Node.js + Redis sorted se
本文实例讲述了PHP swoole和redis异步任务实现方法。分享给大家供大家参考,具体如下: redis异步任务 interface.php <?php for($i=0;$i<100 xss=removed xss=removed>connect(127.0.0.1); $redis->publish...
在学习过程中发现redis的zset还可以用来实现轻量级的延时消息队列功能,虽然可靠性还有待提高,但是对于一些对数据可靠性要求不那么高的功能要求完全可以实现。本次主要采用了redis中zset中的zadd, zrangebyscore 和...
20200728redis相关重要知识点的记录,包含redis通过setnx+expire实现分布式锁,redis单机锁会面临的宕机锁无法释放和执行长时间任务导致超时释放锁,临界区代码没有安全执行的问题,因此出现了redlock红锁,能够保证
3-2 Redis队列秒杀实现 (14:29) 第4章 RabbitMQ:更专业的消息系统实现方案 以RabbitMQ为例讲解了一些专业消息系统的原理,并使用官方的DEMO,演示其中的一个模块的使用方法。了解这类消息系统使用的步骤和应用场景...
下面是想到的几种实现延时任务的方案,总结了一下相应的优势和劣势。 方案 优势 劣势 选用场景 JDK 内置的延迟队列 DelayQueue 实现简单 数据内存态,不可靠 一致性相对低的场景 调度框架和 MySQL 进行...
《Redis入门指南(第2版)》是一本Redis的入门指导书籍,以通俗易懂的方式介绍了Redis基础与实践方面的知识,包括历史与特性、在开发和生产环境中部署运行Redis、数据类型与命令、使用Redis实现队列、事务、复制、...