Lua脚本操作redis

模拟库存扣减

基础版

java 复制代码
@SpringBootTest
class LuaTests {


    @Resource(name="redisTemplate")
    ValueOperations<String,Long> valueOperations;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    final  String priductKey = "product.1";


    @Test
    void test1() throws IOException {
        StringBuilder sb = new StringBuilder();
        sb.append(" local key = KEYS[1] ");
        sb.append(" local qty = ARGV[1] ");
        sb.append(" local redis_qty = redis.call('get',key) ");
        sb.append(" if tonumber(redis_qty) >= tonumber(qty)  then ");
        sb.append("   redis.call('decrby',key,qty) ");
        sb.append("  return  -1 "); // -1 代表的扣减成功了
        sb.append(" else ");
        sb.append("  return tonumber(redis_qty)  "); //返回的当前的库存量 , 0,1,2 .......
        sb.append(" end ");
        RedisScript<Long>  script =  RedisScript.of(sb.toString(),Long.class);

        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            executorService.execute(()->{
               int needQty = RandomUtil.randomInt(1,5);
                Long qty = stringRedisTemplate.execute(script, CollUtil.newArrayList(priductKey), needQty + "");
                if(qty == -1 ){
                    System.out.println(StrUtil.format("{} 扣减成功,需求量是:{}",Thread.currentThread().getId(),needQty));
                } else {
                    System.out.println(StrUtil.format("{} 扣减失败,您的需求量是:{},当前库存量是:{}",Thread.currentThread().getId(),needQty,qty));
                }
            });

        }

     System.in.read();
    }

升级版

java 复制代码
@Test
    void test2() throws IOException {
        final String key1 = "product.1";
        final String key2 = "product.2";
        final String key3 = "product.3";
        valueOperations.set(key1,5l);
        valueOperations.set(key2,10l);
        valueOperations.set(key3,15l);
        StringBuilder sb = new StringBuilder();
        sb.append(" local table = {} ");
        sb.append(" local redis_qtys =  redis.call('mget',unpack(KEYS)) ");
        sb.append(" for i=1, #KEYS do ");
        sb.append("  if  tonumber(ARGV[i]) >  tonumber(redis_qtys[i]) then");
        sb.append("   table[#table + 1] = KEYS[i] .. '=' .. redis_qtys[i]  "); // product.2=56
        sb.append("  end ");
        sb.append(" end ");

        sb.append(" if #table > 0  then "); //如果有任何一个商品库存不足
        sb.append("  return table ");
        sb.append(" end ");
        //能够走到这一行
        sb.append(" for i=1, #KEYS do ");
        sb.append("  redis.call('decrby',KEYS[i],ARGV[i]) ");
        sb.append(" end ");
        sb.append(" return {} ");
        RedisScript<List>  script =  RedisScript.of(sb.toString(),List.class);

        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 1; i++) {
            executorService.execute(()->{
                int needQty1 = RandomUtil.randomInt(1,7);
                int needQty2 = RandomUtil.randomInt(1,10);
                int needQty3 = RandomUtil.randomInt(1,16);
                List ret = stringRedisTemplate.execute(script, CollUtil.newArrayList(key1,key2,key3), needQty1+"",needQty2+"",needQty3+"");
                if(ret.size() == 0 ){
                    System.out.println(StrUtil.format("{} 扣减成功,需求量是:{},{},{}",Thread.currentThread().getId(),needQty1,needQty2,needQty3));
                } else {

                    System.out.println(StrUtil.format("{} 扣减失败,您的需求量是:{},{},{} ",Thread.currentThread().getId(),needQty1,needQty2,needQty3));
                   for(Object obj :ret){
                       System.out.println(obj);
                   }
                }
            });

        }

        System.in.read();
    }
相关推荐
逻各斯5 小时前
redis中的Lua脚本,redis的事务机制
java·redis·lua
阿桢呀8 小时前
Redis实战篇《黑马点评》5
数据库·redis·缓存
Kerwin要坚持日更9 小时前
一文讲解Redis中的主从复制
数据库·redis·缓存
Suk-god9 小时前
【Redis】基础知识入门
数据库·redis·缓存
zfj32110 小时前
手动搭建Redis1主2从+ 3 Sentinel 高可用集群
redis·sentinel·高可用
m0_7482309411 小时前
Redis 通用命令
前端·redis·bootstrap
Struggle Sheep13 小时前
linux安装redis
linux·运维·redis
guihong00415 小时前
Redis 深度解析:高性能缓存与分布式数据存储的核心利器
redis·分布式·缓存
qq_5298353517 小时前
Redis作为缓存和数据库的数据一致性问题
数据库·redis·缓存
知初~21 小时前
出行项目案例
hive·hadoop·redis·sql·mysql·spark·database