RedisLua脚本应用和tonumber()的使用
原创官方文档 http://redisdoc.com/script/eval.html
1、释放分布式锁:
if redis.call(get,KEYS[1]) == ARGV[1] then
return redis.call(del,KEYS[1])
else
return 0
end
PHP中应用:
/**
* 释放锁
* @return bool
*/
public function release()
{
return (bool)$this->redis->eval(释放分布式锁lua, 1, $this->key, $this->value);
}
2、抢购中减库存:需提前将总库存存入redis
if tonumber(ARGV[1]) <= tonumber(redis.call(get, KEYS[1])) then
return redis.call(decrby, KEYS[1], ARGV[1]) + 1
else
return 0
end
tonumber()属于redis内部函数,作用是将参数转为数字(进行大小比较时必须转),否则结果错误。
这里+1目的是确保消费最后一个库存时结果返回的bool值为true
PHP中应用:
/**
* 减库存
* @param $key
* @param $decrement 减量
* @return bool
*/
public function stockDeCrBy($key, $decrement)
{
return (bool)$this->redis->eval(抢购中减库存lua, 1, $key, $decrement);
}
LUA返回多个值:
local stock = tonumber(redis.call(get, KEYS[1]));
if tonumber(ARGV[1]) <= stock then
local stock = tonumber(redis.call(decrby, KEYS[1], ARGV[1]));
return {stock + 1,stock}
else
return {0,stock}
end
/**
* 减库存
* @param $key
* @param $decrement 减量
* @return bool
*/
public function stockDeCrBy($key, $decrement, &$stock)
{
list($res, $stock) = $this->redis->eval(抢购中减库存lua, 1, $key, $decrement);
return (bool)$res;
}
if (!$model->stockDeCrBy(goods_id_123456789, 10, $stock)) {
//此处变量$stock无需定义,因为其在stockDeCrBy是传址
throw new Exception(剩余商品.$stock.件,不够售卖,请增加库存);
}
判断key是否存在使用 redis.call(exists,KEYS[1]) == 1
3、抢购中加销量:不需要提前存总库存入redis
if 1 == redis.call(exists,KEYS[1]) then
if tonumber(ARGV[2]) < (tonumber(ARGV[1]) + tonumber(redis.call(get,KEYS[1]))) then
return 0
else
return redis.call(incrby,KEYS[1],ARGV[1])
end
else
return redis.call(incrby,KEYS[1],ARGV[1])
end
或者定义local局部变量:
local key = KEYS[1];
local increment = ARGV[1];
local stock = ARGV[2];
if 1 == redis.call(exists,key) then
if tonumber(stock) < (tonumber(increment) + tonumber(redis.call(get,key))) then
return 0
else
return redis.call(incrby,key,increment)
end
else
return redis.call(incrby,key,increment)
end
PHP中应用:
/**
* 增销量
* @param $key
* @param $increment 增量
* @param $stock 总库存
* @return bool
*/
public function saleInCrBy($key, $increment, $stock)
{
return (bool)$this->redis->eval(抢购中加销量lua, 1, $key, $increment, $stock);
}
比较复杂的LUA脚本最好是缓存入redis内部,使用evalsha命令对脚本进行复用,免去了无谓的带宽消耗。 http://redisdoc.com/script/evalsha.html
在PHP中的应用: https://blog.csdn.net/Gan_1314/article/details/125296018
版权声明
所有资源都来源于爬虫采集,如有侵权请联系我们,我们将立即删除
itfan123



