[PhalApi实战篇(1)]Redis队列处理异步任务

[7.15]-Redis队列处理异步任务 - 图1

前言

先在这里感谢phalapi框架创始人@dogstar,为我们提供了这样一个优秀的开源框架.

哈喽大家好呀!之前编写的PhalApi入门篇和进阶篇已经过去了好久了,在此之间也回答了很多小伙伴各种各样的问题,这里也希望吧里面一些问的比较多的和比较有趣的以及笔者在使用PhalApi一些新的体会,都提取出来为大家带来一些能够在实际开发中可以使用的技术或思想,那么我们就开始我们实战篇中的第一节 Redis队列处理异步任务

大家希望喵咪在PhalApi实战推出一些什么样的内容?可以私信我邮箱wenzhenxi@vip.qq.com

附上:

喵了个咪的博客:w-blog.cn

官网地址:http://www.phalapi.net/

开源中国Git地址:http://git.oschina.net/dogstar/PhalApi/tree/release

1.为什么需要队列

为什么需要队列?其实已经是一个老生常谈的一个问题了,队列有诸多好处比如:

在项目中,将一些无需即时返回且耗时的操作提取出来,进行了异步队列处理,而这种异步队列处理的方式大大的节省了服务器的请求响应时间,从而提高了系统的吞吐量。 比较通俗易懂的解释就是 一个请求处理一些事情 A 业务耗时 30ms B业务 耗时 20ms 然后发邮件 耗时 50ms ,吧其中的发送邮件 写入队列 有一个专门负责发送邮件的程序接受这个队列的消息在吧邮件发送出去,这样这个请求原来要用100ms现在只需要50ms , 借助队列可以吧很多原本很消耗时间的操作单独有序处理

队列软件也很多:RabbitMQ,KafKa这两款都是非常主流的队列软件PhalApi也有提供对应的扩展程序来去使用,但是需要使用它们的成本对相对高一些需要搭建很多复杂的组件,但是相对redis,redis虽然没有那么多丰富的功能工具但是它也是队列软件中的不二之选

2.理解Redis处理队列特点

对于PHP来说对Redis支持是特别好的,redis的单线程保障了队列不会应为并发的问题导致一条消息多人获取所有也是很适合做为队列传输,PhalApi不仅仅自带简单的Redis库笔者也在它的基础上封装了一个更为完善的redis库,如下:

Redis · 暗夜在火星/PhalApi Library - 码云 - 开源中国

队列主要由两部分组成一部分是客户端一部分是消费端,客户端负责提供消息消费端负责处理队列这样的一个形式

在使用redis队列主要会使用到redis队列中的List类型,List类型可以从左右两边读取和写入数据,这样的形式就可以做到先入先出或者是后入先出这种队列模式

3.具体实践(基于PhalApi-Redis扩展)

客户端的使用比较简单只需要初始化Redis链接后向左边写入数据即可:

客户端:

  1. //redis链接
  2. DI()->redis = new Redis_Lite(DI()->config->get('app.redis.servers'));
  3. //写入队列左边
  4. DI()->redis->set_lPush(队列键名,值, 库名);

关键是消费端的用法,怎么让消费端一直不停的处理队列呢?很多童鞋应该已经想到了利用死循环不停的读取队列处理来解决及时处理的问题,但是这样又会带来一个新的问题,如果说队列空了死循环会不会一直高额的消耗CPU资源啊?由于这点就衍生出来两种具体的用法:

用法一

有的小伙伴就说了,这个还不简单吗?当队列里面没有内容了我就关掉消费端,然后使用crontab过一段时间再启动进行处理,这就没有所谓的死循环CPU消耗的问题了,这种解法如下:

  1. while (true) {
  2. // 读取队列右边
  3. $msg = DI()->redis->get_rPop(队列键名, 库名);
  4. if( !$msg ){
  5. break;
  6. }
  7. // 处理逻辑
  8. .....
  9. }

然后通过crontab进行定时任务即可

用法二

第二种用法是通过redis队列的另外一种机制来解决这类问题,相对于get_rPop还有提供一个方法get_brPop,我们可以看一下这个方法的描述读取队列右边 如果没有读取到阻塞一定时间这个阻塞时间是通过配置文件blocking字段来配置的,使用方式如下

  1. while (true) {
  2. // 读取队列右边
  3. $msg = DI()->redis->get_brPop(队列键名, 库名);
  4. // 处理逻辑
  5. .....
  6. }

这种方法相对上面那种的好处是实时性最好,如果阻塞时间设置的是5秒等待了2秒有消息进来了就里面会进入处理模式

上述方式可以使用Supervisor进行常驻内存执行

总结

本次实战篇为大家讲述了怎么使用Redis来处理队列来处理异步任务,以及队列有什么特点为什么使用redis队列,那么后续的实战篇也会为大家带来比较使用的PhalApi各项技术,如果大家有什么希望喵咪能够加入到实战篇的内容可以@我哦!

注:笔者能力有限有说的不对的地方希望大家能够指出,也希望多多交流!

官网QQ交流群:①群:421032344 ②群:459352221 欢迎大家的加入!

原文: https://www.phalapi.net/wikis/7-15.html