redis延迟队列php,php redis延迟队列,redis延迟队列

本文涉及的产品
云数据库 Tair(兼容Redis),内存型 2GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: redis延迟队列php,php redis延迟队列,redis延迟队列

记得在上一家公司时公司没有延迟队列,直接使用redis list进行使用,如果不到执行时间则继续丢回去,这样的方式太浪费IO,而且没办法保证执行顺序。本文没有使用有赞的redis延迟队列设计,使用的是redis有序集合的特性来完成。大致思路如下:

(1).下单成功通过zadd key score value命令把订单信息写入到集合中,例如

key:order

score:指定要执行的时间戳(单位秒)

value:订单id

集合的最终元素成员如下

score          value

1603620459     202010250100

1603620460     202010250101

(2).通过zrangebyscore命令取需要执行的元素,例如

ZRANGEBYSCORE order (0 1603620500

例如查询score大于0,并且score小于当前时间戳的数据

(3).查询到数据我们应该从集合中删除此元素,使用zrem命令即可,如果删除的失败,说明已经被其他进程消费,可以丢弃。

我编写了一个PHP的实现。

<?php


class DelayQueue

{

   /**

    * name

    * @var string|null

    */

   public static $name = null;


   /**

    * Redis_Handler

    * @var Redis|null

    */

   public static $handler = null;


   /**

    * add

    * @param int $score

    * @param string $value

    * @return int

    */

   public static function add($score, $value)

   {

       return static::$handler->zAdd(static::$name, $score, $value);

   }


   /**

    * get

    * @param int $e_score

    * @param int $s_score

    * @param int $limit

    * @param bool $remove

    * @return array

    */

   public static function get($e_score, $s_score = 0, $limit = 10, $remove = true)

   {

       $list = static::$handler->zRangeByScore(static::$name, $s_score, $e_score, ['limit' => [0, $limit]]);

       if ($remove)

       {

           foreach ($list as $key => $value)

           {

               if (!static::del($value)) unset($list[$key]);

           }

       }


       return $list;

   }


   /**

    * del

    * @param $value

    * @return int

    */

   public static function del($value)

   {

       return static::$handler->zRem(static::$name, $value);

   }

}

(4).生成者的代码:

//1.加载Redis

$redis = new Redis();

$redis->connect('127.0.0.1', 6379);


//2.设置延迟队列

DelayQueue::$name = 'order';

DelayQueue::$handler = $redis;


//3.投递队列

$time = time() + 30; //下单成功30秒需要处理

$orderId = uniqid();

DelayQueue::add($time, $orderId);

(5).消费者代码:

//1.加载Redis

$redis = new Redis();

$redis->connect('127.0.0.1', 6379);


//2.设置延迟队列

DelayQueue::$name = 'order';

DelayQueue::$handler = $redis;


//3.查询时间小于当前时间的队列数据,默认输出10条

$time = time();

$list = DelayQueue::get($time);

foreach ($list as $value)

{

   //输出信息

   echo "订单Id:" . $value . PHP_EOL;


   //发送消息给订单关联的用户(伪代码)

   //sendMsgToUserByOrderId($value);

}

(6).其他从队列取值的写法说明:

(1).在队列中查询time<=1603597141 and time>=0 的元素(同时队列中会自动删除符合条件的元素)

$time = 1603597141;

$list = DelayQueue::get($time);


(2).在队列中查询time<=1603597141 and time>=1603597132 的元素(同时队列中会自动删除符合条件的元素)

$time1 = 1603597413;

$time2 = 1603597132;

$list = DelayQueue::get($time1, $time2);


(3).在队列中查询time<=1603597141 and time>=1603597132 的元素,只返回1条(同时队列中会自动删除这条元素)

$time1 = 1603597555;

$time2 = 1603597132;

$list = DelayQueue::get($time1, $time2,1);


(4).在队列中查询time<=1603597141 and time>=1603597132 的元素返回10条即可,不删除队列数据,仅查看数据

$time1 = 1603597693;

$time2 = 1603597132;

$list = DelayQueue::get($time1, $time2, 10, false);

(7).解决有序集合元素值不得重复的问题:

Redis有序集合中元素内容不得重复,上面实例中都是传递的订单Id,如果我们想投递多次相同订单Id,何如?

(1).Value中传递唯一Id,同订单Id组合的Json形式,例如

$data = [

   'order_id'=>1,

   'order_uniqid'=>uniqid()

];

$res =  DelayQueue::add(time() + 30, json_encode($data));

(2).Value中前X位存储订单Id,后X位存储唯一Id(推荐)

有序集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
2月前
|
缓存 NoSQL PHP
Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出
本文深入探讨了Redis作为PHP缓存解决方案的优势、实现方式及注意事项。Redis凭借其高性能、丰富的数据结构、数据持久化和分布式支持等特点,在提升应用响应速度和处理能力方面表现突出。文章还介绍了Redis在页面缓存、数据缓存和会话缓存等应用场景中的使用,并强调了缓存数据一致性、过期时间设置、容量控制和安全问题的重要性。
55 5
|
2月前
|
设计模式 NoSQL Go
Redis 实现高效任务队列:异步队列与延迟队列详解
本文介绍了如何使用 Redis 实现异步队列和延迟队列。通过 Go 语言的 `github.com/go-redis/redis` 客户端,详细讲解了 Redis 客户端的初始化、异步队列的实现和测试、以及延迟队列的实现和测试。文章从基础连接开始,逐步构建了完整的队列系统,帮助读者更好地理解和应用这些概念,提升系统的响应速度和性能。
64 6
|
2月前
|
存储 NoSQL PHP
PHP与Redis结合使用,提升数据存储性能
随着互联网应用的发展,PHP与Redis的结合成为提升数据存储性能的重要手段。PHP作为流行的服务器端语言,常用于网站开发;Redis作为高性能内存数据库,以其快速读写能力,有效优化数据访问速度,减轻数据库压力。两者结合通过缓存机制显著提升应用响应速度,支持高并发场景下的稳定性和可扩展性。
|
2月前
|
存储 NoSQL 关系型数据库
PHP 使用 Redis
10月更文挑战第22天
61 6
|
3月前
|
消息中间件 存储 NoSQL
如何用Redis实现延迟队列?
综上所述,通过Redis的有序集合和一些基本命令,我们可以轻松地构建出功能完善的延迟队列系统。根据具体需求,可以进一步优化和扩展,以满足高性能和高可靠性的业务需求。
82 1
|
3月前
|
缓存 NoSQL 数据处理
原生php实现redis缓存配置和使用方法
通过上述步骤,你可以在PHP项目中配置并使用Redis作为高性能的缓存解决方案。合理利用Redis的各种数据结构和特性,可以有效提升应用的响应速度和数据处理效率。记得在实际应用中根据具体需求选择合适的缓存策略,如设置合理的过期时间,以避免内存过度消耗。
79 0
|
4月前
|
消息中间件 NoSQL Go
PHP转Go系列 | ThinkPHP与Gin框架之Redis延时消息队列技术实践
【9月更文挑战第7天】在从 PHP 的 ThinkPHP 框架迁移到 Go 的 Gin 框架时,涉及 Redis 延时消息队列的技术实践主要包括:理解延时消息队列概念,其能在特定时间处理消息,适用于定时任务等场景;在 ThinkPHP 中使用 Redis 实现延时队列;在 Gin 中结合 Go 的 Redis 客户端库实现类似功能;Go 具有更高性能和简洁性,适合处理大量消息。迁移过程中需考虑业务需求及系统稳定性。
|
NoSQL PHP Redis
Mac PHP安装Redis扩展
php安装redis的扩展 采用pecl命令进行安装; pecl命令,在使用brew 安装php时,已经为我们安装上了,这里我们直接使用即可。 我们先进入php的bin目录看下命令是否存在,对应路径如下: cd /opt/homebrew/Cellar/php@7.3/7.3.32 这里的7.3为我通过brew install [php@7.3]安装的php具体版本号,大家可以通过ls命令查看文件夹下是否存在pecl命令
1467 0
|
NoSQL PHP Apache
windows下PHP安装Redis扩展不成功的可能原因
windows下PHP安装Redis扩展不成功的可能原因
528 0
windows下PHP安装Redis扩展不成功的可能原因
|
NoSQL Linux PHP
php7安装redis6扩展
php7安装redis6扩展
193 0