模拟库存扣减
基础版
@SpringBootTest
class LuaTests {@Resource(name="redisTemplate")ValueOperations<String,Long> valueOperations;@AutowiredStringRedisTemplate stringRedisTemplate;final String priductKey = "product.1";@Testvoid 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();}
升级版
@Testvoid 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=56sb.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();}