场景说明:

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

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

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

命令:

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. ASP.Net中关于WebAPI与Ajax进行跨域数据交互时Cookies数据的传递

    本文主要介绍了ASP.Net WebAPI与Ajax进行跨域数据交互时Cookies数据传递的相关知识.具有很好的参考价值.下面跟着小编一起来看下吧 前言 最近公司项目进行架构调整,由原来的三层架构改 ...

  2. java从文件中读取数据然后插入到数据库表中

    实习工作中,完成了领导交给的任务,将搜集到的数据插入到数据库中,代码片段如下: static Connection getConnection() throws SQLException, IOExc ...

  3. android在代码中四种设置控件背景颜色的方法(包含RGB)

    转载请注明出处: http://blog.csdn.net/fth826595345/article/details/9208771  TextView tText=(TextView) findVi ...

  4. Revit API创建一个拷贝房间内对象布局命令

    本课程演示创建一个拷贝房间内对象布局命令,完整演示步骤和代码.这个命令把选中房间内的对象复制到其它选中的一个或多个房间中,而且保持与源房间一致的相对位置.通过本讲座使听众知道创建一个二次开发程序很简单 ...

  5. ASP.NET MVC异步验证是如何工作的01,jQuery的验证方式、错误信息提示、validate方法的背后

    ASP.NET MVC借助jQuery的验证机制,提供了一套从客户端到服务端异步验证的解决方案,通常情况下,用起来相当方便.但面对一些相对特殊的情况,可能会遇到验证失效的场景,比如在使用ajax动态异 ...

  6. C# TextWriter类

    来自:https://www.yiibai.com/csharp/c-sharp-textwriter.html C# TextWriter类是一个抽象类.它用于将文本或连续的字符串写入文件.它在Sy ...

  7. Windows 同一时候开启核心显卡与独立显卡(不接显示器启动核芯显卡)

    採用Mp4视频压缩格式编码时,非常耗CPU.所以决定上显卡.进行显卡加速.选择了Intel核心显卡进行视频编码加速,效果非常理想.但如今的问题是:在PC上如何同一时候开启核心显卡与独立显卡.经过几番周 ...

  8. 【linux c】setsockopt 详解

    转自:http://blog.csdn.net/zhonglinzhang/article/details/9183229 功能描述:        获取或者设置与某个套接字关联的选 项.选项可能存在 ...

  9. 犯罪现场调查第一季/全集CSI迅雷下载

    英文译名 CSI (第1季) (2000首播)CBS. 本季看点:<犯罪现场调查>赌城拉斯维加斯吸引着做发财梦的人,也吸引着形形色色的罪犯,该市警察局的犯罪现场调查局在全美国名列第二.该剧 ...

  10. 用自定义的RoundImageView来实现圆形图片(可加边框)

    本文的控件来自:http://blog.csdn.net/alan_biao/article/details/17379925 这个控件不同于之前介绍过的那个框架,这个仅仅能过将图片裁剪为圆形,没能弄 ...