Redis学习之实现优先级消息队列
很久没有写博客了,最近简单的学习了一下Redis,其中学习了一下用Redis实现优先级消息队列。关于更多更为详细的可以在www.redis.cn找到相关资料。
对于熟悉Redis的童鞋提到队列很自然的想到使用Redis的列表类型。其中也自然能够想到LPUSH和RPOP命令实现队列的概念。如果要实现任务队列,只需要让生产者将任务使用LPUSH命令加入到某个键中,另一边让消费者不断使用RPOP命令从该键中取出任务即可。首先我们先进行简单测试,分别打开两个redis-cli实例
在第一个窗口中输入:
127.0.0.1:> LPUSH queue: yayun
(integer)
127.0.0.1:>
第二个窗口输入:
127.0.0.1:> RPOP queue:
"yayun"
127.0.0.1:> LLEN queue:
(integer)
127.0.0.1:>
可以看见马上就取出值了,再次查询的时候发现已经没有记录了,说明已经消费掉了。简单明了的生产者,消费者。
如果我们程序中使用RPOP命令,将导致队列中即使没有任务时,也会每秒都会调用RPOP命令,如果可以实现一旦有新任务加入就通知消费者,也就是我们的程序,那么将是最给力的,Redis都已经替我们想好了,我们可以使用BRPOP命令操作,BRPOP命令和RPOP命令相似,唯一的区别是当列表中没有元素时BRPOP命令会一直阻塞住连接,直到有新的任务加入。我们再次进行简单测试。
BRPOP命令接收两个参数,第一个是键名,第二个是超时时间,单位是秒。当超过了此时间没有获得性元素的话返回nil。如果设置为0,表示不限制等待时间,即如果没有新元素加入列表就会永远阻塞下去。
第一个窗口中输入(没有任务一直阻塞):
127.0.0.1:> BRPOP queue:
第二个窗口中输入:
127.0.0.1:> LPUSH queue: yayun
(integer)
127.0.0.1:>
当我们加入任务时,发现第一个窗口的输入如下:
127.0.0.1:> BRPOP queue:
) "queue:0"
) "yayun"
(.19s)
127.0.0.1:>
可以发现当加入任务时马上消费掉了,元素已经被取走。
下面说说如何实现优先级消息队列,最后结合python来一段简单代码演示一下。BRPOP命令可以同时接收多个键,起完整的命令格式为BRPOP key [ key ... ] timeout,例如BRPOP queue:0 queue:1 0。意思是同时检测多个键,如果所有键都没有元素则一直阻塞,如果其中有一个键有元素会从该键中弹出元素。如果多个键都有元素则按照从左到右的顺序取第一个键中的一个元素。下面进行简单的测试。打开两个实例:
第一个窗口中:
127.0.0.1:> LPUSH queue: yayun
(integer)
127.0.0.1:> LPUSH queue: dengyayun
(integer)
127.0.0.1:>
第二个窗口中:
127.0.0.1:> LPUSH queue: yayun
(integer)
127.0.0.1:> BRPOP queue: queue:
) "queue:0"
) "yayun"
127.0.0.1:> BRPOP queue: queue:
) "queue:1"
) "dengyayun"
127.0.0.1:>
从上面我们可以发现queue:0任务先执行了。好了,说了这么多了相信大家都测试体会到了,下面来一段简单的python脚本进行测试。python操作redis需要安装模块。
从https://github.com/andymccurdy/redis-py下载redis-py-master.zip安装,解压后进入到目录执行python setup.py install即可安装完成。关于相关操作说明这里说的非常清楚https://pypi.python.org/pypi/redis/以及解压后目录里的README.rst文件。都可以进行阅读。
生产着脚本如下:
#!/usr/bin/python import redis def producers():
for i in xrange(1000000):
str='low_task_queue %d' % i
pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
r.lpush('low_task_queue',str) if __name__ == "__main__":
producers()
消费者脚本如下:
#!/usr/bin/python import redis, time def handle(task):
print task
time.sleep(1) def consumer():
pool = redis.ConnectionPool(host='localhost', port=6379, db=0)
r = redis.Redis(connection_pool=pool)
while 1:
result = r.brpop(['high_task_queue', 'low_task_queue'], 0)
handle(result[1]) if __name__ == "__main__":
consumer()
打开2个窗口,分别执行两个脚本,然后打开第3个窗口手动添加元素,模拟优先级队列。
可以看见在处理队列了,我这里停顿了1秒才处理,是为了观看效果。
[root@mysql-server- ~]# python consumer.py
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
打开窗口手动插入元素:
127.0.0.1:> LPUSH high_task_queue 'high_task_queue 9999999'
(integer)
127.0.0.1:>
可以看见优先级队列已经处理。
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
high_task_queue
low_task_queue
low_task_queue
low_task_queue
low_task_queue
参考资料
<<Redis 入门指南>>
总结:
Redis功能强大,简单易用,还需要进一步好好学习。
Redis学习之实现优先级消息队列的更多相关文章
- 【框架学习与探究之消息队列--EasyNetQ(2)】
声明 本文欢迎转载,系博主原创,本文原始链接地址:http://www.cnblogs.com/DjlNet/p/7654902.html 前言 此文章,是承接上篇:[框架学习与探究之消息队列--Ea ...
- RabbitMQ学习笔记五:RabbitMQ之优先级消息队列
RabbitMQ优先级队列注意点: 1.只有当消费者不足,不能及时进行消费的情况下,优先级队列才会生效 2.RabbitMQ3.5以后才支持优先级队列 代码在博客:RabbitMQ学习笔记三:Java ...
- 【框架学习与探究之消息队列--EasyNetQ(1)】
前言 本文欢迎转载,实属原创,本文原始链接地址:http://www.cnblogs.com/DjlNet/p/7603554.html 废话 既然都是废话了,所以大家就可以跳过了,这里是博主有事没事 ...
- Redis 学习(三) —— 事务、消息发布订阅
一.Redis事务 Redis 提供的事务机制与传统的数据库事务有些不同,传统数据库事务必须维护以下特性:原子性(Atomicity), 一致性(Consistency),隔离性(Isolation) ...
- 用 Redis 实现 PHP 的简单消息队列
参考:PHP高级编程之消息队列 消息队列就是在消息的传输过程中,可以保存消息的容器. 常见用途: 存储转发:异步处理耗时的任务 分布式事务:多个消费者消费同一个消息队列 应对高并发:通过消息队列保存任 ...
- redis(五)---- 简单消息队列
消息队列一个消息的链表,是一个异步处理的数据处理引擎.不仅能够提高系统的负荷,还能够改善因网络阻塞导致的数据缺失.一般用于邮件发送.手机短信发送,数据表单提交.图片生成.视频转换.日志储存等. red ...
- 使用redis原生list结构作为消息队列取代celery框架。
1.web后台对大批量的繁重的io任务需要解耦使用分布式异步技术,否则会使接口阻塞,并发延迟,一般就选celery好了.此篇的取代主要是针对取代celery的worker模式.没有涉及到周期和定时模式 ...
- [转载] 基于Redis实现分布式消息队列
转载自http://www.linuxidc.com/Linux/2015-05/117661.htm 1.为什么需要消息队列?当系统中出现“生产“和“消费“的速度或稳定性等因素不一致的时候,就需要消 ...
- 基于Redis的消息队列php-resque
转载:http://netstu.5iunix.net/archives/201305-835/ 最近的做一个短信群发的项目,需要用到消息队列.因此开始了我对消息队列选型的漫长路. 为什么选型会纠结呢 ...
随机推荐
- java基础-day6
第06天 java基础语法 今日内容介绍 u Eclipse断点调试 u 基础语法的练习 第1章 Eclipse断点调试 1.1 Eclipse断点调试概述 Eclipse的断点调试可以 ...
- express 错误处理
原谅我的无知,之前学习express时,没想过需要错误处理.app.js也没认真看. 现在做具体的项目时,需要考虑到出错的情况. 其实有两种: 1.nodejs是单线程,如果挂掉了,网站就会崩溃,需要 ...
- appcompat_v7报错
appcompat_v7如果报找不到资源,value-xx出错.一般就是因为appcompat_v7的版本问题,直接修改api版本至appcompat_v7对应value的最高版本. 我的v7包最高对 ...
- cocos 2dx 通过循环实现界面图形的摆放
首先创建一个一维数组 this.starSprites = new Array(); 然后知道星星的间距和坐标后通过如下代码实现位置的摆放 for(var i = 0; i < 6; i++){ ...
- delphi 分享三个随机字符串
uses math; function GenID:String; var b, x: byte; begin Result := '{'; Randomize; do begin ) > ,) ...
- Linux-文件查找命令find
find - search for files in a directory hierarchy find命令用于在目录层级中查找文件 SYNOPSIS find [-H] [-L] [-P] [-D ...
- CentOS 7安装fail2ban+Firewalld防止SSH爆破与CC攻击
准备工作 1.检查Firewalld是否启用 #如果您已经安装iptables建议先关闭 service iptables stop #查看Firewalld状态 firewall-cmd --sta ...
- Python学习--和 Oracle 交互(2)
当在 mac 电脑上用 Python 读取 oracle 数据库中的中文时,有可能返回数据为“?” 解决方案: 在数据库操作的函数前添加以下代码, import sysreload(sys)sys.s ...
- 存储过程 Mvc 的调用
/// <summary> /// 根据条件,使用存储过程分页查询电影 /// </summary> /// <param na ...
- Linux系统磁盘与分区管理(7)
Linux最传统的磁盘文件系统(filesystem)使用的是EXT4格式,所以要了解文件系统就得要由认识EXT4开始,而文件系统是创建在硬盘上面的,因此我们得了解硬盘的物理组成才行,下面我们回来详细 ...