赞
踩
下单后半小时未付款订单自动取消的实现,延迟队列
类似的需要:
订单的评论如果7天未评价,系统需要自动产生一条评论
订单的15天之后未点击收货,系统需要自动更改为已收货。
。。。
因为是需要一个常驻进程来检查的,我们使用redis存储会更好。
延迟队列
就是需要延迟一段时间后执行。Redis可通过zset来实现。我们可以将有序集合的value 设置为我们的消息任务(orderId),把value的score设置为消息的到期时间,然后轮询获取有序集合的中的到期消息进行处理。
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。
原始返回值:
1) "jack"
2) "2500"
3) "tom"
4) "5000"
5) "peter"
6) "12000"
$redis->zrangebyscore返回值:
array | null
[value1 => score1, value2 => score2]
代码:
<?php class RedisCli { protected static $redis; public static function getRedisInstance($conf){ if(isset(self::$redis)){ return self::$redis; } try{ $redis = new \Redis(); $re = $redis->connect($conf['host'], $conf['port']); if(!$re){ throw new \Exception('connect redis error'); } if(isset($conf['auth'])){ $re = $redis->auth($conf['auth']); if(!$re){ throw new \Exception('redis auth error'); } } self::$redis = $redis; return $redis; }catch(\Exception $e){ throw new \Exception($e->getMessage()); } } public static function addOrder($redis, $key, $orderId){ $ttl = time() - 600; $re = $redis->zadd($key, $ttl, $orderId); return $re; } public static function getOrders($redis, $key, $num = 1){ /* array(1) { [3334]=> float(1573703310) } */ $orders = $redis->zrangebyscore($key, 0, time(), ['limit'=>[0, $num], 'withscores'=>TRUE]); if(!$orders){ return []; } // 移除元素 foreach($orders as $k => $v){ $redis->zrem($key, $k); } return $orders; } public static function getAndDeleteOrder($redis, $key, $num = 1){ $script = " local score= redis.call( 'ZRANGEBYSCORE', KEYS[1], ARGV[1], ARGV[2], 'WITHSCORES' , 'LIMIT' , ARGV[3] , ARGV[4] ) if score ~= false and #score ~= 0 then local i = 1 while i <= #score do redis.call('ZREM', KEYS[1] , score[i]) i=i+2 end end return score"; $result = $redis->eval($script, [$key, 0, time(), 0, $num], 1); /* $redis->eval的返回结果: array(4) { [0]=> string(4) "3334" [1]=> string(10) "1573701647" [2]=> string(4) "3333" [3]=> string(10) "1573702072" } */ $return = []; $count = count($result); if($count > 0){ for($i = 0; $i < $count; $i+=2){ $return[$result[$i]] = $result[$i + 1]; } } /* array(1) { [3334]=> string(10) "1573702856" } */ return $return; } } $conf = ['host'=>'127.0.0.1', 'port'=>6379, 'auth'=>'123456']; $redis = RedisCli::getRedisInstance($conf); $key = 'orderkey'; $orderId = 3334; // 添加 RedisCli::addOrder($redis, $key, $orderId); // 消费,由于可能存在多进程的并发,使用Lua优化版, while(true){ try{ // $data = RedisCli::getOrders($redis, $key); $data = RedisCli::getAndDeleteOrder($redis, $key); if(empty($data)){ sleep(1); }else{ var_dump($data); } }catch(\Exception $e){ } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。