场景说明:

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

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

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

命令:

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. hdu1242 Rescue(BFS +优先队列 or BFS )

    http://acm.hdu.edu.cn/showproblem.php?pid=1242 题意:     Angel被传说中神秘的邪恶的Moligpy人抓住了!他被关在一个迷宫中.迷宫的长.宽不超 ...

  2. Reactor与Proactor比较

    from http://www.cnblogs.com/dawen/archive/2011/05/18/2050358.html 1.标准定义 两种I/O多路复用模式:Reactor和Proacto ...

  3. PostgreSQL学习手册(目录)

    原文地址:http://www.cnblogs.com/stephen-liu74/archive/2012/06/08/2315679.html 事实上之前有很长一段时间都在纠结是否有必要好好学习它 ...

  4. 【POI】maven引用POI的依赖,XSSFWorkbook依旧无法使用的问题。

    maven项目引用POI的jar: <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --> <dependenc ...

  5. Oracle 备份、恢复单表或多表数据步骤

    Oracle 备份.恢复单表或多表数据步骤,适用于 Oracle 8.9.10.        *备份单表或多表数据: exp user/password@server file=filefullpa ...

  6. Git:常用命令(一)

    取得项目的Git 仓库 从当前目录初始化 git init 初始化后,在当前目录下会出现一个名为.git 的目录,所有Git 需要的数据和资源都存放在这个目录中.不过目前,仅仅是按照既有的结构框架初始 ...

  7. Linux 安全信息查看

    终端登录情况 last ssh登录情况 cat /var/log/secure | grep -i "accepted password" 定时任务 cat /var/log/cr ...

  8. Button 自定义图片,代码绘制样式,添加音效的方法

    Button自己在xml文件中绑定监听器 <!-- 设定onclick属性,然后在activity中定义相应的方法 --> <!-- 通过xml布局中通过button的android ...

  9. main函数的参数argc和argv

    版权声明:本文为博主原创文章,转载请注明CSDN博客源地址!共同学习,一起进步~ https://blog.csdn.net/Eastmount/article/details/20413773 该篇 ...

  10. 脚本中export不起作用的原因分析

    #!bin/bash export PATH=$PATH:/usr/lib/java/jre export PATH=$PATH:/usr/lib/java/bin ---path 结果发现直接运行. ...