很久没有写博客了,最近简单的学习了一下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学习之实现优先级消息队列的更多相关文章

  1. 【框架学习与探究之消息队列--EasyNetQ(2)】

    声明 本文欢迎转载,系博主原创,本文原始链接地址:http://www.cnblogs.com/DjlNet/p/7654902.html 前言 此文章,是承接上篇:[框架学习与探究之消息队列--Ea ...

  2. RabbitMQ学习笔记五:RabbitMQ之优先级消息队列

    RabbitMQ优先级队列注意点: 1.只有当消费者不足,不能及时进行消费的情况下,优先级队列才会生效 2.RabbitMQ3.5以后才支持优先级队列 代码在博客:RabbitMQ学习笔记三:Java ...

  3. 【框架学习与探究之消息队列--EasyNetQ(1)】

    前言 本文欢迎转载,实属原创,本文原始链接地址:http://www.cnblogs.com/DjlNet/p/7603554.html 废话 既然都是废话了,所以大家就可以跳过了,这里是博主有事没事 ...

  4. Redis 学习(三) —— 事务、消息发布订阅

    一.Redis事务 Redis 提供的事务机制与传统的数据库事务有些不同,传统数据库事务必须维护以下特性:原子性(Atomicity), 一致性(Consistency),隔离性(Isolation) ...

  5. 用 Redis 实现 PHP 的简单消息队列

    参考:PHP高级编程之消息队列 消息队列就是在消息的传输过程中,可以保存消息的容器. 常见用途: 存储转发:异步处理耗时的任务 分布式事务:多个消费者消费同一个消息队列 应对高并发:通过消息队列保存任 ...

  6. redis(五)---- 简单消息队列

    消息队列一个消息的链表,是一个异步处理的数据处理引擎.不仅能够提高系统的负荷,还能够改善因网络阻塞导致的数据缺失.一般用于邮件发送.手机短信发送,数据表单提交.图片生成.视频转换.日志储存等. red ...

  7. 使用redis原生list结构作为消息队列取代celery框架。

    1.web后台对大批量的繁重的io任务需要解耦使用分布式异步技术,否则会使接口阻塞,并发延迟,一般就选celery好了.此篇的取代主要是针对取代celery的worker模式.没有涉及到周期和定时模式 ...

  8. [转载] 基于Redis实现分布式消息队列

    转载自http://www.linuxidc.com/Linux/2015-05/117661.htm 1.为什么需要消息队列?当系统中出现“生产“和“消费“的速度或稳定性等因素不一致的时候,就需要消 ...

  9. 基于Redis的消息队列php-resque

    转载:http://netstu.5iunix.net/archives/201305-835/ 最近的做一个短信群发的项目,需要用到消息队列.因此开始了我对消息队列选型的漫长路. 为什么选型会纠结呢 ...

随机推荐

  1. Job Interview: Why Only 3 Questions Really Matter

    Even for the most fearless amongst us, job interviews can be nerve wracking. In order to give us the ...

  2. HDU3488 Tour

    Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submi ...

  3. 1.java面向对象编程三大特性之封装

    封装即把一个对象的属性.行为等放在一个实体类中隐藏起来,不允许外部对其进行修改,但是被封装的属性.行为会对外提供一个接口与外部联系,这个对外的接口通常情况下就是set().get()方法.可以通过se ...

  4. poj2481

    题意:给定一些线段(s, e),起点为s,终点为e,求每一段线段被多少线段包含(不包括相等) 思路:很明显的树状数组题目..但是做的时候想了挺久..(下面的x为线段起点, y为线段终点) 做法1:先对 ...

  5. android延时弹出软键盘

    searchEditView.setFocusable(true); searchEditView.setFocusableInTouchMode(true); searchEditView.requ ...

  6. Windows 7/Vista下安装Oracle Developer Suit遇到的几个问题

    http://blog.csdn.net/pan_tian/article/details/8016318 Oracle Developer Suite (ODS) 10g是在Windows 7/Vi ...

  7. 电子书推荐--《Python灰帽子》,python黑客编程

    点此在线阅读 <Python灰帽子>是由知名安全机构Immunity Inc的资深黑帽Justin Seitz主笔撰写的一本关于编程语言Python如何被广泛应用于黑客与逆向工程领域的书籍 ...

  8. Method not found: 'System.Data.Entity.ModelConfiguration.Configuration.XXX

    使用EF flument API  修改映射数据库字段的自增长 modelBuilder.Entity<Invoice>().Property(p => p.Id).HasDatab ...

  9. Spring IOC 容器源码分析 - 创建单例 bean 的过程

    1. 简介 在上一篇文章中,我比较详细的分析了获取 bean 的方法,也就是getBean(String)的实现逻辑.对于已实例化好的单例 bean,getBean(String) 方法并不会再一次去 ...

  10. jQuery小案例

    Jquery例子1_占位符使用需求: 点击第一个按钮后 自动去check 后面是否有按钮没有选中, 如有则提示错误消息. <html> <head> <script ty ...