1.模拟库存扣减,扣到0后还会一直扣,不能保证原子性
package com.by;
import cn.hutool.core.util.StrUtil;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.ValueOperations;
import javax.annotation.Resource;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@SpringBootTest
class DecryDemoTest {
@Resource(name="redisTemplate")
private ValueOperations<String,Long> valueOperations;
private final String key = "protect#01";
/**
* 模拟库存扣减
*/
@Test
void test() {
//设置库存为5
valueOperations.set(key, 5l);
//开启一个线程池
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 1; i <= 10;i++){
//执行 每个人买一份
executorService.execute(() -> {
Long decrement = valueOperations.decrement(key, 1);
if (decrement>=0){
System.out.println(StrUtil.format("线程{},扣减成功{}",Thread.currentThread().getName(),decrement));
}else{
System.out.println(StrUtil.format("线程{},扣减失败{}",Thread.currentThread().getName(),decrement));
}
});
}
}
}
2.模拟库存扣减,扣到0之后不会一直扣,保证原子性
package com.by;
import cn.hutool.core.collection.CollectionUtil;
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.StringRedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
@SpringBootTest
class LuaDemoTest {
@Autowired
private StringRedisTemplate redisTemplate;
/**
* 模拟库存扣减,扣到0之后不会一直扣,保证原子性
*/
@Test
void test() {
String key = "pro#01";
//设置商品库存量
redisTemplate.opsForValue().set(key,"5");
//需求量
String qty="2";
//lua脚本
//我希望能扣减成功返回1,不能扣减成功返回0
StringBuilder luasb=new StringBuilder();
//空格不能少
//书写lua脚本语言 local定义变量
luasb.append(" local key=KEYS[1] ");
luasb.append(" local qty=redis.call('get',key); ");
//库存量大于需求量
luasb.append(" if tonumber(qty)>=tonumber(ARGV[1])");
luasb.append(" then ");
luasb.append(" redis.call('decrby',KEYS[1],ARGV[1]) ");
luasb.append(" return 1 ");
luasb.append(" else ");
luasb.append(" return 0 ");
luasb.append(" end ");
RedisScript<Long> redisScript = RedisScript.of(luasb.toString(), Long.class);
//执行结果
Long aLong = redisTemplate.execute(redisScript, CollectionUtil.newArrayList(key), qty);
System.out.println(aLong);
}
}