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

redis的list类型天生支持用作消息队列。由于redis的list是使用双向链表实现的,保存了头尾节点,所以在列表头尾两边插取元素都是非常快的。所以可以直接使用redis的list实现消息队列,只需简单的两个指令lpush和rpop或者rpush和lpop。简单示例如下:

public class MessageQueue {

    private final String redisChanel1 = "redisChanel1";
private final String redisChanel2 = "redisChanel2"; private String redisHost = "10.5.31.155";
private int redisPort = ;
private Jedis redis; @Before
public void before() {
redis = new Jedis(redisHost, redisPort);
} @Test
public void pubChanel1() throws InterruptedException {
for (int i = ; i < ; i++) {
redis.lpush(redisChanel1, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 第" + i + "条消息");
Thread.sleep(Math.round(Math.floor(Math.random() * )));
}
} @Test
public void pubChanel2() throws InterruptedException {
for (int i = ; i < ; i++) {
redis.lpush(redisChanel2, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 第" + i + "条消息");
Thread.sleep(Math.round(Math.floor(Math.random() * )));
}
} @Test
public void sub() throws InterruptedException {
while (true) {
String message1 = redis.rpop(redisChanel1);
System.out.println(redisChanel1 + "-->" + message1);
Thread.sleep();
String message2 = redis.rpop(redisChanel2);
System.out.println(redisChanel2 + "-->" + message2);
Thread.sleep();
}
} @After
public void after() {
redis.close();
}
}

先后运行pubChanel1、pubChanel2、sub方法,可以看到类似如下输出:

redisChanel1-->2018-09-28 10:23:44 第0条消息
redisChanel2-->2018-09-28 10:23:46 第0条消息
redisChanel1-->2018-09-28 10:23:44 第1条消息
redisChanel2-->2018-09-28 10:23:47 第1条消息
redisChanel1-->2018-09-28 10:23:46 第2条消息
redisChanel2-->null
redisChanel1-->2018-09-28 10:23:47 第3条消息
redisChanel2-->2018-09-28 10:23:49 第2条消息
redisChanel1-->2018-09-28 10:23:48 第4条消息
redisChanel2-->null
redisChanel1-->2018-09-28 10:23:49 第5条消息

以上实现原理非常简单,但是由于消费者取消息是循环+sleep实现的,所以会出现如下问题:

  1. 需要考虑消费者拿到空消息的情况(输出结果中出现了null)。
  2. 如果生产者速度大于消费者消费速度,消息队列长度会一直增大,时间久了会占用大量内存空间。
  3. 消费者存在资源浪费的情况。

索性redis还支持另外一个命令:brpop,这个命令只有当list中有元素的时候才会返回,没有元素时会阻塞,直到阻塞超时返回null。那么改变下sub方法的写法如下:

@Test
public void sub() {
while (true) {
List<String> messages = redis.brpop(0, redisChanel1, redisChanel2);
for (String message : messages) {
System.out.println(message);
}
}
}

其中,brpop中的第一个参数值为0表示无超时时间,没有取到消息的时候一直阻塞下去。

redis(五)---- 简单消息队列的更多相关文章

  1. Redis实现简单消息队列

    http://www.jianshu.com/p/9c04890615ba 任务异步化 打开浏览器,输入地址,按下回车,打开了页面.于是一个HTTP请求(request)就由客户端发送到服务器,服务器 ...

  2. Redis+php-resque实现消息队列

      服务器硬件配置 Dell PowerEdge R310英特尔单路机架式服务器 Intel Xeon Processor X3430 2.4GHz, 8MB Cache 8GB内存(2 x 4GB) ...

  3. Delayer 基于 Redis 的延迟消息队列中间件

    Delayer 基于 Redis 的延迟消息队列中间件,采用 Golang 开发,支持 PHP.Golang 等多种语言客户端. 参考 有赞延迟队列设计 中的部分设计,优化后实现. 项目链接:http ...

  4. Redis 学习笔记(六)Redis 如何实现消息队列

    一.消息队列 消息队列(Messeage Queue,MQ)是在分布式系统架构中常用的一种中间件技术,从字面表述看,是一个存储消息的队列,所以它一般用于给 MQ 中间的两个组件提供通信服务. 1.1 ...

  5. 如何使用NODEJS+REDIS开发一个消息队列

    作者: RobanLee 原创文章,转载请注明: 萝卜李 http://www.robanlee.com MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应 ...

  6. simple简单消息队列

    一:介绍 1.优缺点 简单,但是耦合性较高. 这种模式是生产者与消费者一一对应,就是一个产生者,有一个消费者来消费. 如果,多个消费者想消费一个队列中的消息就不适合了.这种情况在后面会接着介绍. 2. ...

  7. Spring Cloud(7):事件驱动(Stream)分布式缓存(Redis)及消息队列(Kafka)

    分布式缓存(Redis)及消息队列(Kafka) 设想一种情况,服务A频繁的调用服务B的数据,但是服务B的数据更新的并不频繁. 实际上,这种情况并不少见,大多数情况,用户的操作更多的是查询.如果我们缓 ...

  8. php和redis怎么实现消息队列

    把瞬间服务器的请求处理换成异步处理,缓解服务器的压力,实现数据顺序排列获取.本文主要和大家分享php和redis如何实现消息队列,希望能帮助到大家. redis实现消息队列步骤如下: 1).redis ...

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

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

随机推荐

  1. C++字符集和词法记号以及符号常量

    C++字符集 大小写的英文字母:A~Z,a~z 数字符号:0~9 特殊字符:!#%*()等 关键字:C++预定义的单词 标识符:程序员声明的单词,它命名程序正文中的一些实体 文字:在程序中直接使用符号 ...

  2. Java提升四:Stream流

    1.Stream流的定义 Stream是Java中的一个接口.它的作用类似于迭代器,但其功能比迭代器强大,主要用于对数组和集合的操作. Stream中的流式思想:每一步只操作,不存储. 2.Strea ...

  3. 060、Java中定义有返回值有参数的方法

    01.代码如下: package TIANPAN; /** * 此处为文档注释 * * @author 田攀 微信382477247 */ public class TestDemo { public ...

  4. 模拟一次sql注入攻击

    在你的web服务目录下 创建一个php文件如下 <?php $conn = db_connect(); $sql = sprintf('update users set password = & ...

  5. 数据库-----catalog与schema简介

    在SQL环境下Catalog和Schema都属于抽象概念,主要用来解决命名冲突问题 一个数据库系统包含多个Catalog,每个Catalog包含多个Schema,每个Schema包含多个数据库对象(表 ...

  6. asp.net+sql数据库学生信息管理系统

    一款学生信息管理系统送给大家. 功能部分: 1.教师管理(添加,修改,删除,查看) 2.学生管理(添加,修改,删除,查看) 3.班级管理(添加,修改,删除,查看) 4.学生成绩管理(添加,修改,删除, ...

  7. 吴裕雄 Bootstrap 前端框架开发——Bootstrap 字体图标(Glyphicons):glyphicon glyphicon-chevron-right

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name ...

  8. linux添加一个已经存在用户到一个用户组

    在使用virtual-box的共享文件时,在虚拟机中共享文件的用户为root,用户组为vboxsf, 所以需要将自己添加到vboxsf这组当中去,一开始使用useradd老是失败,后来才查到要用use ...

  9. 指令——df

    df是disk free 的简称,这个指令的功能和作用是查看磁盘空间. 可以加上 -h 的选项,来提高可读性. [he@localhost ~]$ df -h文件系统(磁盘名称)      总容量  ...

  10. 105-PHP使用var_dump查看类的类型

    <?php class ren{ //定义人类 } class mao{ //定义猫类 } $ren1=new ren(); //实例化人类 $mao1=new mao(); //实例化猫类 $ ...