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/ 最近的做一个短信群发的项目,需要用到消息队列.因此开始了我对消息队列选型的漫长路. 为什么选型会纠结呢 ...
随机推荐
- (动规 或 最短路)Help Jimmy(poj 1661)
http://poj.org/problem?id=1661 Description "Help Jimmy" 是在下图所示的场景上完成的游戏. 场景中包括多个长度和高度各不相同的 ...
- 12.DataGrid的columns的特性
- 深入探讨 Java 类加载器(转)
原帖地址:https://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要 ...
- unigui结合JS方法
在js中界面上所有组件都当成html里来控制 1.控制按钮事件 document.getElementById(MainForm.UniButton4.getId()).click(); 这个方法让J ...
- 关于等效的物理意义 On the Physical Meaning of Equivalence
当我们谈到两个物理概念是等效的,这意味着: 1.它们拥有同样的属性.例如质量和能量都可以弯曲空间. 2.它们可以在设计实验中无法区分彼此.例如恒星系统中行星的质量与恒星的引力. 3.它们可以互相转化. ...
- python 使用json格式转换
什么是json: JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式.易于人阅读和编写.同时也易于机器解析和生成.它基于JavaScript Programm ...
- WPF自定义TabControl样式
WPF自定义TabControl,TabControl美化 XAML代码: <TabControl x:Class="SunCreate.Common.Controls.TabCont ...
- Mac下更改Mysql5.7的默认编码为utf8
Mac上从官方安装完Mysql5.7后,有一部分的字符集默认为latin1,而非utf8,为避免乱码的产生,本文介绍将所有字符集设置为utf8 查看当前字符集编码 show variables lik ...
- 201621123018《Java程序设计》第9周学习报告
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 泛型个人认为可以理解为一种模糊的类型,在里面写入各种方法,程序员可以根据需要再创建具体类型的对象,然后调用泛型 ...
- 自用 docker-compose
version: '3.1' services: mysql: image: mysql: command: --default-authentication-plugin=mysql_native_ ...