美文网首页
通过redis+lua实现加减库存

通过redis+lua实现加减库存

作者: wyatt_plus | 来源:发表于2019-05-26 21:20 被阅读0次

    一. 场景

    下单后库存校验或者秒杀场景下,有很多利用“锁”的方案来解决问题。但是加锁其实是一件性价比很低的事,所以我们采用用redis+lua的方式来实现这个功能。

    二. 思路

    阶段一
    在库存加减逻辑中分为2个步骤:STEP1.读取库存STEP2.读取库存
    利用其他方法例如"锁"等,也就是想控制好STEP2一定要紧跟STEP1,本质上就是确保获取的库存的最新的数据为最新。
    阶段二
    在相对较高的并发场景下,redis被常用作库存管理,我们需要通过最小成本的改动来实现库存的限制。但是redis的读取库存+读取库存一般都是有上层应用代码控制,有没有办法在一个函数调用中能串行执行这俩个步骤了?
    阶段三
    众所周知,redis是单线程的,并且现在已经支持lua脚本,那是不是可以利用该组合实现我们的场景了?

    三. 设计方案

    这个方案就很简单了,直接利用redistemplate执行lua脚本

    四. 代码

    4.1 lua脚本代码样例

        private static final String GET_COUPON_CODE =
                "local values = redis.call('hmget',KEYS[1],'recvCnt','couponCnt');\n" +  //lua返回value的数组
                        "if tonumber(values[1]) < tonumber(values[2]) then \n" +       //lua的数组索引从1开始 values[1] = recvCnt,values[2] = couponCnt
                        "  redis.call('hincrby',KEYS[1],'recvCnt',1);\n" +
                        "  return true;\n" +
                        "else\n " +
                        "  return false;\n" +
                        "end\n";
    

    4.2 redis调用lua脚本

            //执行调用
            execute(GET_COUPON_CODE, keys);
            //此处将数值类型转化为Long
            public Long execute(String redisScript,List<String> keys){
                  RedisScript<Long> REDIS_SCRIPT = new DefaultRedisScript<>(redisScript, Long.class);
                  return redisTemplate.execute(REDIS_SCRIPT,keys);
        }
    

    4.3 lua基本用法

      redis.call()
      redis.pcall()
      call与pcall基本上一样。脚本报错时,call会直接报错,pcall不会报错,会把错误信息放到lua table 的err字段中。
    

    五. 说明

    1.记得利用“\n”分行,也可以利用string的append拼接
    2.values[n]对应有序数组keys,需要控制好各数据顺序
    3.lua的数组索引从1开始

    六. 总结

    我们先分析场景,通过多种方案对比,选用了redis+lua的组合来满足我们的业务需要。利用redis单线程的特点,以及redis2.6版本后开始对lua的支持,我们采用redis执行lua脚本来确保我们查询+修改的串行执行。后面我们展示了code的实现案例,以及介绍了lua脚本的一些注意事项,可以依葫芦画瓢形式自己实现自己的需求。综合而言,我们分析场景应先分析其核心问题,然后利用一些更简洁的方法或小技巧来落地。

    相关文章

      网友评论

          本文标题:通过redis+lua实现加减库存

          本文链接:https://www.haomeiwen.com/subject/oaiftctx.html