Lua脚本的使用

一、使用lua脚本扣减单个商品的库存

@SpringBootTest
class LuaTests {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

@Test
    void test3() {

        for (int i = 1; i <= 5; i++) {
            stringRedisTemplate.opsForValue().set("product."+i,String.valueOf(i));
        }

    }

 @Test
    void test2() {

        StringBuilder sb = new StringBuilder();
        sb.append(" local key = KEYS[1] "); // 你要扣减的key :product.1
        sb.append(" local qty = ARGV[1] "); // 你要扣减的数量,需求量
        sb.append(" local redis_qty = redis.call('get',key) "); //获取redis库存实际数量
        sb.append(" if tonumber(redis_qty) >= tonumber(qty) then ");//需求量与库存量对比
        sb.append("     redis.call('decrby',key,qty) "); //满足
        sb.append("   return -1  "); //满足
        sb.append(" else ");
        sb.append("   return tonumber(redis_qty) ");  //不满足,就给剩余库存量 ,0 1 2 。。。。
        sb.append(" end ");
        RedisScript<Long> luaScript = RedisScript.of(sb.toString(), Long.class);
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        for (int i = 1; i <= 5; i++) {

            executorService.execute(()->{
                int qty = RandomUtil.randomInt(1,6);
                Long count = stringRedisTemplate.execute(luaScript, CollUtil.newArrayList("product.5"),String.valueOf(qty));
                if (count == -1L) {
                    System.out.println(Thread.currentThread().getId() + " 扣减成功,扣减了-> "+ qty);
                } else {
                    System.out.println(Thread.currentThread().getId() + "扣减失败,需求量是:"+qty+",剩余库存量:"+count);
                }
            });
        }

        // 线程睡眠3秒 
        ThreadUtil.safeSleep(3000);

    }
}

二、使用lua脚本扣减多个商品的库存

@Test
    void test4() {

        StringBuilder sb = new StringBuilder();
        sb.append(" local table = {}  "); // 你要扣减的key :product.1
        sb.append(" local values =  redis.call('mget',  unpack(KEYS) )"); // [product.1,product.2]   =>  product.1 product.2
        sb.append(" for i = 1, #KEYS   do  ");
        sb.append("   if  tonumber(ARGV[i]) > tonumber(values[i])   then ");
        // ..的意思就是组合,也就是字符串相加
        sb.append("     table[#table + 1] =  KEYS[i] .. '=' .. values[i] "); //product.1=23
        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> luaScript = RedisScript.of(sb.toString(), List.class);

        List<StockProduct> stockProducts =  new ArrayList<>();
        stockProducts.add(new StockProduct(5,1));
        stockProducts.add(new StockProduct(4,2));

        List<String> keys = stockProducts.stream().map(it -> "product." + it.getId()).collect(Collectors.toList());
        Object[] qtys = stockProducts.stream().map(it -> it.getQty() + "").toArray();
        List<String> list = stringRedisTemplate.execute(luaScript,
                keys,
                qtys);
        if(list.isEmpty()){
            System.out.println("库存冻结成功");
        } else {

            for (String key_qty : list) {
                String[] split = key_qty.split("=");
                System.out.println(split[0] + "库存不足,剩余库存量:" + split[1]);
            }

        }


        ThreadUtil.safeSleep(3000);

    }

三、通过分布式锁,扣减商品的库存

package com.by;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.RandomUtil;
import com.by.moder.Student;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import javax.annotation.Resource;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@SpringBootTest
class SetNXTests {

    @Autowired
    StringRedisTemplate stringRedisTemplate;

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


    @Test
    void Test() {
        //线程池
        ExecutorService executorService = Executors.newFixedThreadPool(5);

        for (int i = 1; i <=5; i++) {
            executorService.execute(()->{
                //某一个工人
                String ioId = "IO"+ RandomUtil.randomInt(1,1000);
                while (true){
                    // 判断是否存在
                    Boolean b = valueOperations.setIfAbsent("lock.product.1",ioId+":"+ DateUtil.now());
                    if(b){
                        System.out.println(Thread.currentThread().getId()+"获取到了分布式锁");
                        //执行业务
                        ThreadUtil.safeSleep(3000);

                        // 执行业务成功后
                        stringRedisTemplate.delete("lock.product.1");
                        System.out.println(Thread.currentThread().getId()+"释放了分布式锁");
                        break;
                    }else {
                        //Thread.currentThread().getId() :当前线程的id
                        System.out.println(Thread.currentThread().getId()+"没有获取到分布式锁");
                        ThreadUtil.safeSleep(1000);
                    }
                }
            });
        }
        //睡眠
        ThreadUtil.safeSleep(100000);
    }
}

相关推荐

  1. Lua脚本使用

    2024-04-02 14:30:05       16 阅读
  2. Redis使用Lua脚本

    2024-04-02 14:30:05       45 阅读
  3. lua脚本基本语法,以及Redis中简单使用

    2024-04-02 14:30:05       45 阅读
  4. <span style='color:red;'>Lua</span><span style='color:red;'>脚本</span>

    Lua脚本

    2024-04-02 14:30:05      28 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-02 14:30:05       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-02 14:30:05       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-02 14:30:05       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-02 14:30:05       20 阅读

热门阅读

  1. react--常见hook

    2024-04-02 14:30:05       12 阅读
  2. 25.死锁

    25.死锁

    2024-04-02 14:30:05      18 阅读
  3. Git 实战教程

    2024-04-02 14:30:05       21 阅读
  4. 数据流模型——【数据科学与工程算法基础】

    2024-04-02 14:30:05       14 阅读
  5. CPU狂飙900%,该怎么处理

    2024-04-02 14:30:05       15 阅读
  6. 【OpenCV进阶】图像中添加中文字幕

    2024-04-02 14:30:05       21 阅读
  7. 低代码与系统集成:革新企业应用开发的新动力

    2024-04-02 14:30:05       14 阅读
  8. MYSQL08_页的概述、内部结构、行格式

    2024-04-02 14:30:05       18 阅读
  9. 面试中的MVCC到底是什么意思?

    2024-04-02 14:30:05       19 阅读
  10. Spring与SpringMVC常用注解

    2024-04-02 14:30:05       16 阅读
  11. elasticsearch之多条件查询

    2024-04-02 14:30:05       18 阅读
  12. Redis

    Redis

    2024-04-02 14:30:05      15 阅读
  13. 递归---算法

    2024-04-02 14:30:05       19 阅读