1. 首页>
  2. 技术文章>
  3. redis+lua做秒杀的库存判断

redis+lua做秒杀的库存判断

9/5/22 2:25:18 PM 浏览 1731 评论 0

redis lua

“lua 脚本于 2.6.0 版本开始支持,Redis 使用同一个 Lua 脚本解释器去执行所有的脚本命令,并且在脚本命令执行期间,其它的脚本命令和 Redis 命令将会等待其执行完成,所以 Lua 脚本执行命令具有原子性。 有个注意的点,就是如果脚本命令执行时间太长,那么会影响服务的性能,其它的客户端执行命令都会受到影响。 若Lua 脚本执行期间出错,那么脚本执行过程将会中断,并返回一个 error 给客户端。

比如下面这段代码,会有并发问题,最后的库存是负数:

var key = "goods:A";
_redis.SetIncr(key, 10);
//测试并发执行,如果没有并发问题,理论上应该库存为0,但执行下来,库存却为负数
Parallel.For(1, 20, (index) =>
{
    var stock = Convert.ToInt32(_redis.GetIncr(key));
    if (stock > 0){_redis.Incr(key, -1);}
});            
var lastStock = Convert.ToInt32(_redis.GetIncr(key));
return lastStock;

而下面的代码则不会出现负数:

var key = "goods:A";
_redis.SetIncr(key, 10);
 //测试并发执行,如果没有并发问题,理论上应该库存为0,结果也确实为0
Parallel.For(1, 20, (index) => {
        var command = $@"if tonumber(redis.call('get',{key}'))>0 then 
            redis.call('decr','{key}')
                return 1
        else
                return 0
        end";
    var result = _redis.ExecCommand(command);
});
var lastStock = Convert.ToInt32(_redis.GetIncr(key));
return lastStock;

如果不用LUA的话,我们也可以直接就decr一下,取得decr后的值,如果为负数,则库存不足,报错提示,然后把库存重置为0。

网友讨论