当前位置:   article > 正文

下单后半小时未付款订单自动取消的实现,延迟队列_zrangebyscore 订单时间

zrangebyscore 订单时间

下单后半小时未付款订单自动取消的实现,延迟队列

类似的需要:
订单的评论如果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]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

代码:

<?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){

	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/200994?site
推荐阅读
相关标签
  

闽ICP备14008679号