场景说明:

·用于处理比较耗时的请求,例如批量发送邮件,如果直接在网页触发执行发送,程序会出现超时

·高并发场景,当某个时刻请求瞬间增加时,可以把请求写入到队列,后台在去处理这些请求

·抢购场景,先入先出的模式

命令:

rpush + blpop 或 lpush + brpop
rpush : 往列表右侧推入数据 
blpop : 客户端阻塞直到队列有值输出

简单队列:

simple.php
$stmt = $pdo->prepare('select id, cid, name from zc_goods limit 200000');$stmt->execute();while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {    $redis->rPush('goods:task', json_encode($row));} $redis->close();

获取20000万个商品,并把json化后的数据推入goods:task队列

queueBlpop.php
// 出队while (true) {    // 阻塞设置超时时间为3秒    $task = $redis->blPop(array('goods:task'), 3);    if ($task) {        $redis->rPush('goods:success:task', $task[1]);        $task = json_decode($task[1], true);        echo $task['id'] . ':' . $task['cid'] . ':' . 'handle success';        echo PHP_EOL;    } else {        echo 'nothing' . PHP_EOL;        sleep(5);    }}

设置blpop阻塞时间为3秒,当有数据出队时保存到goods:success:task表示执行成功,当队列没有数据时,程序睡眠10秒重新检查goods:task是否有数据出队

cli 模式执行命令:
php simple.phpphp queueBlpop.php

优先级队列

思路:

blpop 有多个键时,blpop会从左至右遍历键,一旦一个键能弹出元素,客户端立即返回。例如:

blpop key1 key2 key3 key4

从key1到key4遍历,如果哪个key有值,则弹出这个值,若多个key同时有值时,优先弹出排在左边的key。

priority.php
// 设置优先级队列$high = 'goods:high:task';
$mid = 'goods:mid:task';$low = 'goods:low:task';
 $stmt = $pdo->prepare('select id, cid, name from zc_goods limit 200000');
$stmt->execute();while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) 
{    // cid 小于100放在低级队列    if ($row['cid'] < 100) 
{        $redis->rPush($low, json_encode($row));    
}    // cid 100到600之间放在中级队列    elseif ($row['cid'] > 100 && $row['cid'] < 600) 
{        $redis->rPush($mid, json_encode($row));    }   
 // cid 大于600放在高级队列     else {        $redis->rPush($high, json_encode($row));    }
}$redis->close();
priorityBlop.php
// 优先级队列$high = 'goods:high:task';$mid = 'goods:mid:task';$low = 'goods:low:task';// 出队while(true){    // 优先级高的队列放在左侧    $task = $redis->blPop(array($high, $mid, $low), 3);    if ($task) {        $task = json_decode($task[1], true);        echo $task['id'] . ':' . $task['cid'] . ':' . 'handle success';        echo PHP_EOL;    } else {        echo 'nothing' . PHP_EOL;        sleep(5);    }}

优先级高的队列放在blpop命令左侧,依次排序,blpop命令会依次弹出high, mid, low队列的值

cli 模式执行命令:
php priority.phpphp priorityBlpop.php

延迟队列

思路:

可以用一个有序集合来保存延迟任务,member保存任务内容,score保存(当前时间 + 延时时间)。用时间作为score。程序只要用有序集合的第一条任务的score和当前时间做比较,如果当前时间比score小,说明有序集合的所有任务还没到执行时间。

delay.php
$stmt = $pdo->prepare('select id, cid, name from zc_goods limit 200000');$stmt->execute();while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {    $redis->zAdd('goods:delay:task', time() + rand(1, 300), json_encode($row));}

将20万条任务导入有序集合goods:delay:task,所有任务延迟到之后的1秒到300秒内执行

delayHandle.php

while (true) {// 因为是有序集合,只要判断第一条记录的延时时间,例如第一条未到执行时间    // 相对说明集合的其他任务未到执行时间

$rs = $redis->zRange('goods:delay:task', 0, 0, true);

// 集合没有任务,睡眠时间设置为5秒

    if (empty($rs)) {        
                echo 'no tasks , sleep 5 seconds' . PHP_EOL;sleep(5);continue;}
     $taskJson = key($rs);   
              $delay = $rs[$taskJson];   
              $task = json_decode($taskJson, true);   
      $now = time();// 到时间执行延时任务   
     if ($delay <= $now) {       

// 对当前任务加锁,避免移动移动延时任务到任务队列时被其他客户端修改

        if (!($identifier = acquireLock($task['id']))) {         
       continue;}        

// 移动延时任务到任务队列

$redis->zRem('goods:delay:task', $taskJson);        
$redis->rPush('goods:task', $taskJson);       
echo $task['id'] . ' run ' . PHP_EOL;        

// 释放锁

releaseLock($task['id'], $identifier);    } 
    else {       

// 延时任务未到执行时间

 $sleep = $delay - $now;       

// 最大值设置为2秒,保证如果有新的任务(延时时间1秒)进入集合时能够及时的被处理

    $sleep = $sleep > 2 ? 2 :$sleep;       
    echo 'wait ' . $sleep . ' seconds ' . PHP_EOL;        sleep($sleep);   
    }
}

这个文件对有序集合内的延迟任务做处理,如果延迟任务到了执行时间,则把延迟任务移动到任务队列中

queueBlpop.php
// 出队while (true) {   
// 阻塞设置超时时间为3秒   
$task = $redis->blPop(array('goods:task'), 3);   
if ($task) {       
$redis->rPush('goods:success:task', $task[1]);       
$task = json_decode($task[1], true);       
echo $task['id'] . ':' . $task['cid'] . ':' . 'handle success';       
echo PHP_EOL;    } else {       
echo 'nothing' . PHP_EOL;sleep(5);   
    }
}

处理任务队列中的任务

cli模式下执行命令:
php delay.phpphp delayHanlde.phpphp queueBlpop.php

Redis 实现队列http://igeekbar.com/igeekbar/post/436.htm的更多相关文章

  1. redis消息队列简单应用

    消息队列出现的原因 随着互联网的高速发展,门户网站.视频直播.电商领域等web应用中,高并发.大数据已经成为基本的标识.淘宝双11.京东618.各种抢购.秒杀活动.以及12306的春运抢票等,他们这些 ...

  2. (转)java redis使用之利用jedis实现redis消息队列

    应用场景 最近在公司做项目,需要对聊天内容进行存储,考虑到数据库查询的IO连接数高.连接频繁的因素,决定利用缓存做. 从网上了解到redis可以对所有的内容进行二进制的存储,而java是可以对所有对象 ...

  3. 分布式日志2 用redis的队列写日志

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  4. logstash解耦之redis消息队列

    logstash解耦之redis消息队列 架构图如下: 说明:通过input收集日志消息放入消息队列服务中(redis,MSMQ.Resque.ActiveMQ,RabbitMQ),再通过output ...

  5. 预热一下吧《实现Redis消息队列》

    应用场景 为什么要用redis?二进制存储.java序列化传输.IO连接数高.连接频繁 一.序列化 这里编写了一个java序列化的工具,主要是将对象转化为byte数组,和根据byte数组反序列化成ja ...

  6. Redis分布式队列解决文件并发的问题

    1.首先将捕获的异常写到Redis的队列中 public class MyExceptionAttribute : HandleErrorAttribute { public static IRedi ...

  7. 【高并发简单解决方案】redis缓存队列+mysql 批量入库+php离线整合

    原文出处: 崔小拽 需求背景:有个调用统计日志存储和统计需求,要求存储到mysql中:存储数据高峰能达到日均千万,瓶颈在于直接入库并发太高,可能会把mysql干垮. 问题分析 思考:应用网站架构的衍化 ...

  8. RabbitMQ与Redis做队列比较

    本文仅针对RabbitMQ与Redis做队列应用时的情况进行对比 具体采用什么方式实现,还需要取决于系统的实际需求简要介绍RabbitMQRabbitMQ是实现AMQP(高级消息队列协议)的消息中间件 ...

  9. Redis 消息队列的实现

    概述 Redis实现消息队列有两种形式: 广播订阅模式:基于Redis的 Pub/Sub 机制,一旦有客户端往某个key里面 publish一个消息,所有subscribe的客户端都会触发事件 集群订 ...

  10. java-spring基于redis单机版(redisTemplate)实现的分布式锁+redis消息队列,可用于秒杀,定时器,高并发,抢购

    此教程不涉及整合spring整合redis,可另行查阅资料教程. 代码: RedisLock package com.cashloan.analytics.utils; import org.slf4 ...

随机推荐

  1. [C# 基础知识系列]专题八: 深入理解泛型(二)

    引言: 本专题主要是承接上一个专题要继续介绍泛型的其他内容,这里就不多说了,就直接进入本专题的内容的. 一.类型推断 在我们写泛型代码的时候经常有大量的"<"和"& ...

  2. VC2010中"Include Directories" 和 "Additional Include Directories"的区别

    右键一个Project,可以发现有两个地方设置Include的相关目录: 1. VC++ Directories -> Include Directories2. C/C++ -> Gen ...

  3. Android的学习之路(三)项目的启动过程和安装过程具体解释

    应用的安装和启动过程: 安装:第一步:java的编译器会把这个.java文件编译成.class文件           第二部:Android的SDK提供了一个dx工具,这个工具把.class文件转义 ...

  4. C# CSGL

    转.修改自ShareIdeas文章C# 基于CSGL opengl OpenGL是一个功能强大的开放图形库(Open Graphics Library).其前身是SGI公司为其图形工作站开发的IRIS ...

  5. 苹果无法连接到itunes store怎么办

    方法1:设置--还原--还原网络设置,再进app store就可以了.方法2:重置访问限制“设置”–> “通用” –> “访问限制”,开启访问限制5秒,然后再关闭访问限制.方法3:重置当前 ...

  6. JAVA 项目中使用 H2 数据库

    为什么要使用H2数据库 H2数据库是可以嵌入到JAVA项目中的,因为只需要导入一个jar包即可,所以非常的方便. 项目中导入H2 将H2的jar包放到classpath里即可,我是用的maven,ma ...

  7. HTTP协议学习【转】

    面试过程中又一个常见的问题,http协议,因为做服务器开发如果用http协议的话,现在各种开源软件都封装好了,python中只需要简单的继承定义好的类,重写get或者post等方法,几行代码就可以搭建 ...

  8. 样条之埃尔米特(Hermite)插值函数

    核心代码: ////////////////////////////////////////////////////////////////////// // 埃尔米特等距插值 /////////// ...

  9. xenapp 6.5 客户端插件第一次安装总是跳到官网

    部署完xenapp6.5后,在没有安装插件的客户端登录时,会出现“下载客户端插件”界面 其实网上已经有很多解决方案,大同小已,只是不知道为什么不适合我安装的版本而已.我安装时最新的版本xenapp 6 ...

  10. [leetcode]Minimum Path Sum @ Python

    原题地址:https://oj.leetcode.com/problems/minimum-path-sum/ 题意: Given a m x n grid filled with non-negat ...