生产环境为了提升库存操作的速度,使用lua脚本扣减库存,在本地单机环境没有问题,阿里云集群环境的时候,遇到错误
``command keys must in same slot``
lua 脚本
``$scriptSha = self::$redis->get(self::STOCK_SCRIPT_SHA);
if (!$scriptSha) {
$script = <<<luascript
if tonumber(ARGV[1]) >= 0 then
return redis.call('HINCRBY', KEYS[1], KEYS[2], ARGV[1])
else
local store = tonumber(redis.call("HGET", KEYS[1], KEYS[2]))
if store == nil or store < math.abs(tonumber(ARGV[1])) then
return -1
else
return redis.call('HINCRBY', KEYS[1], KEYS[2], ARGV[1])
end
end
luascript;
$scriptSha = self::$redis->script('load', $script);
self::$redis->set(self::STOCK_SCRIPT_SHA, $scriptSha);
}
$stockKey = ($isPre ? self::STOCK_PRESALE : self::STOCK_SALE) . $productId;
$result = self::$redis->evalSha($scriptSha, [$stockKey, self::STOCK_SALE.$supplyId, $quantity], 2); //-1表示库存不足``
这个是使用php redis
扩展执行命令 evalsha和eval函数的第二个参数是数组,把keys
和argv
都放同一个数组,后面的数字2
表示key
的个数。lua数组索引是从1开始的,所以这边2表示前两个数keys的变量,后面的是argv的变量
推荐的解决方法是在key的共性上加{}
。
比如productStock:10000
,是商品10000的库存hash,调整调整key的设置,{productStock}:10000
,另外就是hash 的field也按这个格式,
比如单机情况下设置库存hset productStock:10000 stock 100
需要调整key和field的结构 hset {productStock}:10000 {productStock}:stock 100
这样在分配到solt的时候,就会根据productStock
进行hash处理,从而分配到同一个solt。solt。个solt。