业务需求

本文是以laravel框架来介绍redis队列,具体用法你可以参考http://www.cnblogs.com/lengthuo/p/7277260.html
最近接受一个很简单的东西,(说起来很简单,硬是搞了2天。)我们业务中的一些定时是在晚上执行,但是有的定时必须推送微信消息给用户,为了不影响客户的休息,我们之后想把发去推迟这个任务。
对于我们开发来说,我们只需要知道2件事,入队列和出队列。

入队列

非常简单,我们只需要把数据放到队列中就行了,这里选用redis来作为我们的容器来存储队列,当然你也可以选择用数据库,或者其他的,laraevel支持好多中方式。
redis中用list去存储队列,但是当遇到延迟发送的时候,其实是使用redis的zset(有序的集合列表)来存储的队列。因为有延迟时间吗,我们知道redis的zset的数据结构,有一个value和score ,score是用来排序的,laravel很巧妙的用它来存储发送的时间戳。当然这些其实我们都不需要知道,在laravel框架中,QueueRedis已经封装的非常好了,我们只需要简单的调用

 //方法一 使用内置函数
$job = (new SendWechatMessage($data))->onQueue('queue-name')->delay($delay);
dispatch($job); //方法二 使用门面
//当没有延迟的时候,redis是直接存到list中的
\Queue::push(new SendWechatMessage($data), '', 'queue-name');
//有延迟的时候存入的是zset类型中的
\Queue::later($delay, new SendWechatMessage($data), '', 'redpacket');

在这推荐一个工具
rdm.app 可视化的工具去操作redis,日志中还会有显示对redis操作的日志。很好用,极力推荐。

出队列

laravel中我们只需要简单的启动队列任务就行了,当然laravel文档讲解的更清楚,我就不想说了,我只是简单的提一下几点注意的,和一些原理的东西。

启动队列的方式

queue:work 默认只执行一次队列请求, 当请求执行完成后就终止;
queue:listen 监听队列请求, 只要运行着, 就能一直接受请求, 除非手动终止;
queue:work --daemon 同 listen 一样, 只要运行着, 就能一直接受请求, 不一样的地方是在这个运行模式下, 当新的请求到来的时候, 不重新加载整个框架, 而是直接 fire 动作.
能看出来, queue:work --daemon 是最高级的, 一般推荐使用这个来处理队列监听.
注意: 使用 queue:work --daemon , 当更新代码的时候, 需要停止, 然后重新启动, 这样才能把修改的代码应用上。

原理

首先对存入队列的值进行分析
无延迟队列,直接使list存入,然后在queue:listen 的时候

    public function listen($connection, $queue, $delay, $memory, $timeout = 60)
{
$process = $this->makeProcess($connection, $queue, $delay, $memory, $timeout);
while (true) {//无限循环,所以耗费资源,建议选择使用work命令
$this->runProcess($process, $memory);
}
}

一直从redis list中去取数据。所以一旦有生产者放入,就会很快的被消费之监听。也是非常简单的一种模式
有延迟队列,我只说在laravel中的实现,可能每一种框架都会有不同的实现。
在redis中是由zset来存储延迟队列值得,当有一个延迟队列推送来之后,会存入到redis的zset中,value为要存入的redis中的值,而score为time()+要推迟的时间,所以score存入的是时间戳,laravel框架中在解析的时候会组装一句命令发给redis服务器,
zrangebyscore queues:queue-name:delayed -inf 1504105422
这条命令的意思是:返回小于1504105422时间戳的值,也就是说每一次执行的时候,laravel都是拿当前的时间戳值和redis第一条比较(默认是顺序的,并且第一条是最小的)
说到这是不是豁然开朗,如果不明白可以私聊我,也可以多看看,我相信读完你必有收获。

如果你跟debug的话,就会发现其实laravel包装的所有操作只是来组装数据,最后直接发给redis服务器来处理,然后返回结果。其实就是这么简单。laravel包装的太过于完美,以至于我们什么都不用做。只是简单2行代码就实现了对redis消息队列的操作。

总结

有的时候我们放眼去看,对于这种多种服务交互的时候,原理都是一样的,就比如我们操作mysql,程序肯定不会认识,程序只负责组装sql语句,最后都是会交给mysql服务器来处理,redis也一样,我们只需要组装redis的命令,最后发给redis服务器,他只需要给我们返回结果就可以了。希望本篇文章对你有用。

      路漫漫其修远兮,吾将上下而求索

redis实现消息队列的更多相关文章

  1. Redis 做消息队列

    一般来说,消息队列有两种场景,一种是发布者订阅者模式,一种是生产者消费者模式.利用redis这两种场景的消息队列都能够实现.定义: 生产者消费者模式:生产者生产消息放到队列里,多个消费者同时监听队列, ...

  2. Redis作为消息队列服务场景应用案例

    NoSQL初探之人人都爱Redis:(3)使用Redis作为消息队列服务场景应用案例   一.消息队列场景简介 “消息”是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更 ...

  3. redis resque消息队列

    Resque 目前正在学习使用resque .resque-scheduler来发布异步任务和定时任务,为了方便以后查阅,所以记录一下. resque和resque-scheduler其优点在于功能比 ...

  4. 【springboot】【redis】springboot+redis实现发布订阅功能,实现redis的消息队列的功能

    springboot+redis实现发布订阅功能,实现redis的消息队列的功能 参考:https://www.cnblogs.com/cx987514451/p/9529611.html 思考一个问 ...

  5. 【Redis】php+redis实现消息队列

    在项目中使用消息队列一般是有如下几个原因: 把瞬间服务器的请求处理换成异步处理,缓解服务器的压力 实现数据顺序排列获取 redis实现消息队列步骤如下: 1).redis函数rpush,lpop 2) ...

  6. Lumen开发:结合Redis实现消息队列(1)

    1.简介 Lumen队列服务为各种不同的后台队列提供了统一的API.队列允许你推迟耗时任务(例如发送邮件)的执行,从而大幅提高web请求速度. 1.1 配置 .env文件的QUEUE_DRIVER选项 ...

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

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

  8. sping+redis实现消息队列的乱码问题

    使用spring支持redis实现消息队列,参考官方样例:https://spring.io/guides/gs/messaging-redis/ 实现后在运行过程中发现消费者在接收消息时会出现乱码的 ...

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

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

  10. NoSQL初探之人人都爱Redis:(3)使用Redis作为消息队列服务场景应用案例

    一.消息队列场景简介 “消息”是在两台计算机间传送的数据单位.消息可以非常简单,例如只包含文本字符串:也可以更复杂,可能包含嵌入对象.消息被发送到队列中,“消息队列”是在消息的传输过程中保存消息的容器 ...

随机推荐

  1. [PS相关]DAS,NAS,SAN三种存储技术比较

    随着数据量一直在快速增长,存储技术也在快速的更新以满足需求和推动创新.当存储被提到的时候,它不仅仅局限于存储容量,还有其他的需求比如数据保护,数据备份,数据访问速度等等. NAS-网络存储设备(Net ...

  2. 初学 Python(十三)——匿名函数

    初学 Python(十三)--匿名函数 初学 Python,主要整理一些学习到的知识点,这次是匿名函数. # -*- coding:utf-8 -*- #关键字lambda定义的函数都是匿名函数 #做 ...

  3. 蓝桥杯比赛java 练习《立方变自身》

    立方变自身 观察下面的现象,某个数字的立方,按位累加仍然等于自身.1^3 = 1 8^3  = 512    5+1+2=817^3 = 4913   4+9+1+3=17... 请你计算包括1,8, ...

  4. An internal error occurred during: "Launching web on MyEclipse Tomcat"

    An internal error occurred during: "Launching web on MyEclipse Tomcat" 解决办法1 1.首先关闭MyEclip ...

  5. Xamarin.Forms(二) 返回页面的数据刷新

    这几天在做一个课程表的小程序,遇到了这样一个问题: app打开便是课程表的页面,如果课程表页面没有数据的话需要跳转到同步课表页面模拟登陆教务管理系统获取课表,并显示在课程表页面,这样就需要从同步课表页 ...

  6. java自学找工作经历

    断断续续的,折腾了7个多月,学完了在网上购买的培训机构J2EE的全套课程.期间各种蛋疼看另一篇博客 http://www.cnblogs.com/work396/p/6791488.html 直接说找 ...

  7. 【我的漫漫跨考路】有生之年·调完了BUG--冒泡排序C++版本

    正文之前 今天去牛客网试了试一些实战编程题,感觉贼有意思,但是也很难,挑了个成绩排序的算法题我就开始怼! 对我一个编程经验并不是很丰富的人来说,确实算是个挑战了. 所以我满满当当的搞了四个小时多,才算 ...

  8. 初学Python之 字符串 索引 分片

    字符串是字符的有序集合,可以通过其位置来获得具体的元素. 在python中,字符串中的字符是通过索引来提取的,索引从0开始. python可以取负值,表示从末尾提取,最后一个为-1,倒数第二个为-2, ...

  9. charAt()的功能

    <script type="text/javascript"> var str="Hello world!" document.write(str. ...

  10. 13. Roman to Integer【leetcode】

    Roman to Integer Given a roman numeral, convert it to an integer. Input is guaranteed to be within t ...