/*
*  -3:库存未初始化
*  -2:库存不足
*  -1:不限库存
*  大于等于0: 剩余库存(扣减之后剩余的库存), 直接返回-1
*/
Redis::invoke(function (ESRedis $redis) {
	$userId   = (10000 * microtime(true)) . rand(100, 9999);
	$num      = rand(1, 3);
	$goodsKey = "skill:goods:1";
	$orderKey = "skill:order:1";

	$script = <<<SCRIPT
	
   if redis.call('exists',KEYS[1]) ~= 1 then
	   return -3
   end
   
   local stock =  tonumber(redis.call('get',KEYS[1]))
   local num = tonumber(ARGV[1])
   if stock == -1 then
		return -1
   end
   
   if stock >= num then
		redis.call('lpush',KEYS[2],ARGV[2])
		return redis.call('incrby',KEYS[1],0-num)
   end
   
   return -2
SCRIPT;
	return $redis->rawCommand([
		'EVAL',
		$script,
		2,
		$goodsKey,
		$orderKey,
		$num,
		$userId . ',' . $num
	]);
});
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
$key = 'buy';
$limitNum = 100;
$ttl = 1;
Redis::invoke(function (ESRedis $redis) use ($key, $limitNum, $ttl) {
	$lua = <<<SCRIPT
	redis.call('zAdd',KEYS[1],tonumber(ARGV[2]),ARGV[3])
	redis.call('zRemRangeByScore',KEYS[1],0,tonumber(ARGV[2])-tonumber(ARGV[1]))
	redis.call('expire',KEYS[1],tonumber(ARGV[1]))
	local num = redis.call('zCount',KEYS[1],0,tonumber(ARGV[2]))
	if num > tonumber(ARGV[4]) then
		return 1
	else
		return 0
	end
SCRIPT;

	$score = time();
	$nonce = uniqid() . (10000 * microtime(true));
	return $redis->rawCommand([
		'EVAL',
		$lua,
		1,
		$key,
		$ttl,
		$score,
		$nonce,
		$limitNum,
	]);
});
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