模拟库存扣减
基础版
@SpringBootTest
class LuaTests {
@Resource(name="redisTemplate")
ValueOperations 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 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();
}
升级版
@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 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();
}