一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式。利用redis这两种场景的消息队列都能够实现。
定义:

  • 生产者消费者模式:生产者生产消息放到队列里,多个消费者同时监听队列,谁先抢到消息谁就会从队列中取走消息;即对于每个消息只能被最多一个消费者拥有。
  • 发布者订阅者模式:发布者生产消息放到队列里,多个监听队列的消费者都会收到同一份消息;即正常情况下每个消费者收到的消息应该都是一样的。

那么如此多的MQ产品,为什么要使用redis作消息队列呢?以下附上一份总结了别人的一些report或blog的表格,以及当初用来说服整个team的一句结论。

MQ Env. Weight Disadvantage      
RabbitMQ Erlang Heavy Bad scalability;Low speed;    
ZeroMQ C Light difficult for development    
ActiveMQ Java - Low performance      
Redis C - Low performance while enqueuing big data (>= 10k) 

Redis is easy to use and configure since we have experience in Redis, and most importantly, its performance satisfies our requirement.

Then, how to use redis as a MQ?

首先,redis的队列实际在代码逻辑中不需要由我们自己实现,因此一个所谓的 RedisMQ 对象实际是一个 redis key以及对其操作的一些封装。

PubSub Mode:

redis 从 2.0.0 版本开始支持 pub/sub 指令。详情见 http://redis.io/topics/pubsub

实现思想很简单,Publisher调用redis的publish方法往特定的channel发送消息,Subscriber在初始化的时候要subscribe到该channel,一旦有消息就会立即接收。

比较简单的demo可参见:http://shift-alt-ctrl.iteye.com/blog/1867454 ,此链接博客中写得已较详细,本文便不再赘述。

Producer/Consumer Mode:

该方法是借助redis的list结构实现的。

Producer调用redis的lpush往特定key里塞入消息,Consumer调用brpop去不断监听该key。

producer:

 // producer code
String key = "demo:mq:test";
String msg = "hello world";
redisDao.lpush(key, msg);

consumer:

 // consumer code
String key = "demo:mq:test";
while (true) {
// block invoke
List<String> msgs = redisDao.brpop(BLOCK_TIMEOUT, listKey);
if (msgs == null) continue;
String jobMsg = msgs.get(1);
processMsg(jobMsg);
}

当有多个consumers的时候,它会按照brpop调用的顺序分派消息,并非随机。

BLOCK_TIMEOUT不建议设成infinity(有些redis驱动也直接不支持inifinity),我们目前设成30(单位是秒)情况良好。

P.S. 本文时间较久远,适合redis 2的版本,不保证redis自己会不会有其他新特性 ;同时消息队列产品有很多种,这里列的只是早年常用的,近两三年的kafka和阿里的rocketmq也很火,至于怎么选择,一部分是根据数据量,若数据量不大,容错要求不是极高,redis是个高效开发易维护的好选择;如果数据量很大或对消息准确性有一定要求,那应当考虑更成熟的消息队列产品比如kafka等。所以mq的选型并不是本文的重点,本文只是介绍一下基于redis 2.6的mq的简单封装实现。

Redis 做消息队列的更多相关文章

  1. Redis除了做缓存--Redis做消息队列/Redis做分布式锁/Redis做接口限流

    1.用Redis实现消息队列 用命令lpush入队,rpop出队 Long size = jedis.lpush("QueueName", message);//返回存放的数据条数 ...

  2. 程序员过关斩将--redis做消息队列,香吗?

    Redis消息队列 在程序员这个圈子打拼了太多年,见过太多的程序员使用redis,其中一部分喜欢把redis做缓存(cache)使用,其中最典型的当属存储用户session,除此之外,把redis作为 ...

  3. Redis做消息队列

    1.连接从Redis中获取日志文件并存储到ES中 [root@Logstash ~]# vim /usr/local/logstash/config/redis.conf input {     be ...

  4. 使用Redis做消息队列

    基于内存的单线程数据库,使Redis的线程安全性极高.而Redis的双向链表数据类型(List)天生就可作为消息队列存储消息. 在这里就不说消息队列的等等一些优点.但是补充一下Redis的List类型 ...

  5. RabbitMQ跟Redis做消息队列的区别

    区别 https://www.zhihu.com/question/20795043 https://blog.csdn.net/dd18709200301/article/details/79077 ...

  6. Redis做消息队列文章两篇

    介绍:http://www.cnblogs.com/lhfcws/p/3732535.html 具体做法:http://shift-alt-ctrl.iteye.com/blog/1867454 另外 ...

  7. 使用Redis Stream来做消息队列和在Asp.Net Core中的实现

    写在前面 我一直以来使用redis的时候,很多低烈度需求(并发要求不是很高)需要用到消息队列的时候,在项目本身已经使用了Redis的情况下都想直接用Redis来做消息队列,而不想引入新的服务,kafk ...

  8. PHP使用Redis实现消息队列

    消息队列可以使用MySQL来实现,可以参考博客PHP使用MySQL实现消息队列,虽然用MySQL可以实现,但是一般不这么用,因为MySQL的数据都存在硬盘中,而从硬盘中对MySQL的操作,I/O花费的 ...

  9. rabbitmq和redis用作消息队列的区别

    将redis发布订阅模式用做消息队列和rabbitmq的区别: 可靠性redis :没有相应的机制保证消息的可靠消费,如果发布者发布一条消息,而没有对应的订阅者的话,这条消息将丢失,不会存在内存中:r ...

随机推荐

  1. 【ASP.NET】复制单个文件同时到多个目录

    有时候,当我们更新了一个dll文件后,需要将该dll文件复制到到不同的文件夹中,手动操作会很麻烦,因此可以考虑利用程序实现. 利用powershell批量复制 示例代码如下: $source=&quo ...

  2. maven打包

    1.利用maven-jar-plugin <build> <plugins> <!-- The configuration of maven-jar-plugin --& ...

  3. STL源码学习----lower_bound和upper_bound算法

    转自:http://www.cnblogs.com/cobbliu/archive/2012/05/21/2512249.html 先贴一下自己的二分代码: #include <cstdio&g ...

  4. 如何在eclipse中通过Juit进行单元测试

    1.什么是Junit Junit即单元测试,是JAVA语言的单元测试框架,是对程序的一个方法所进行的测试 一般都是由程序员自己通过Junit来进行测试,因此单元测试也叫程序员测试: 如果测试人员熟悉程 ...

  5. Wakez计算与压缩的思考

    大部分人认为,比尔盖茨在1981年说过这样一句话:640K ought to be enough for anybody.(640个kB对任何人来说都应该足够了).不过后来比尔盖茨否认自己说过这句话. ...

  6. 用U盘安卓esxi虚拟机出现 error loading /s.v00 错误解决办法

    前段时间用 一个 白色的 东芝U盘 给戴尔 R720服务器安装 esxi 6.0时,在加载到/s.v00 找个文件时出现错误,大致为: error loading /s.v00 compressed ...

  7. Delphi容器类之---Tlist,TStringlist,THashedStringlist的效率比较

    转载自:http://www.ylzx8.cn/windows/delphi/73200.html 本人在做一个测试,服务器是IOCP的,我假定最大链接数是50000个. 测试背景:如果每个链接之间的 ...

  8. ORA-12638:身份证明检索失败

    本地Sqlplus 连一远程数据库,出现 ORA-12638: 身份证明检索失败,pl/sql developer 也是同样的问题,tnsping 是没有问题的. 找到本地的sqlnet.ora文件, ...

  9. 【Android】一种提高Android应用进程存活率新方法

    [Android]一种提高Android应用进程存活率新方法 SkySeraph Jun. 19st 2016 Email:skyseraph00@163.com 更多精彩请直接访问SkySeraph ...

  10. mysql 连接池超时

    var mysql = require('mysql'); var pool = mysql.createPool({ host: 'localhost', user: 'nodejs', passw ...