Redisson的分布式锁的简单实现
更多请参考官网:
redisson的GitHub:https://github.com/redisson/redisson/wiki
环境:springboot2.2.5,mybatis,redis,
1.Maven依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.8.0</version>
</dependency>
2.Yaml
server:
port: 8099
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/redis_demo?serverTimezone=GMT%2B8
username: root
password: 123456
hikari: # https://github.com/brettwooldridge/HikariCP (uses milliseconds for all time values)
maximumPoolSize: 10
minimumIdle: 2
idleTimeout: 600000
connectionTimeout: 30000
maxLifetime: 1800000
# Redis数据库索引(默认为0)
redis:
database: 0
# Redis服务器地址
host: 192.168.221.136
# Redis服务器连接端口
port: 7000
# Redis服务器连接密码(默认为空)
password:
# 连接池最大连接数(使用负值表示没有限制)
jedis:
pool:
max-active: 200
# 连接池最大阻塞等待时间(使用负值表示没有限制)
# max-wait: -1
# 连接池中的最大空闲连接
max-idle: 10
# 连接池中的最小空闲连接
min-idle: 0
# 连接超时时间(毫秒)
timeout: 10000
## 该配置节点为独立的节点,有很多同学容易将这个配置放在spring的节点下,导致配置无法被识别
mybatis:
mapUnderscoreToCamelCase: true
typeAliasesPackage: com.ls.pojo
mapperLocations: classpath:mappers/*.xml
3.RedisSonConfig配置类
@Configuration
public class RedisSonConfig {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private String port;
@Value("${spring.redis.password}")
private String password;
@Bean
public RedissonClient getRedisson() {
Config config = new Config();
config.useSingleServer().setAddress("redis://" + host + ":" + port);
//config.useSingleServer().setAddress("redis://" + host + ":" + port).setPassword(password);
//添加主从配置
//config.useMasterSlaveServers().setMasterAddress("").setPassword("").addSlaveAddress(new String[]{"", ""});
return Redisson.create(config);
}
}
4.主要业务代码及实现
@Transactional(rollbackFor = Exception.class)
@Override
public Boolean killItemV4(Long killId, Integer buyNum) throws Exception {
Boolean result = false;
String keyId = String.valueOf(killId);
final String lockKey = new StringBuffer().append(killId).append("-RedisSonLock").toString();
RLock lock = redisSonUtils.getRLock(lockKey);
try {
/**
* 第一个参数30s=表示尝试获取分布式锁,并且最大的等待获取锁的时间为30s
* 第二个参数10s=表示上锁之后,10s内操作完毕将自动释放锁
*/
Boolean cacheRes = lock.tryLock(30, 10, TimeUnit.SECONDS);
if (cacheRes) {
//TODO:核心业务逻辑的处理
//先从redis查库存
stockNum = (Integer) redisUtil.get(keyId);
logger.info("redis库存:" + stockNum);
if (stockNum == null) {
TbItem dbTbItem = tbItemMapper.selectByPrimaryKey(killId);
stockNum = dbTbItem.getNum();
redisUtil.set(keyId, stockNum);
}
if (stockNum <= 0) {
throw new Exception("库存不足01!");
}
if (stockNum >= 0) {
//先更新redis库存
Long kcNum = redisUtil.decr(keyId, buyNum);
logger.info("redis剩余库存:" + kcNum);
stockNum -= buyNum;
if (kcNum.intValue() != stockNum) {
throw new Exception("系统错误!");
}
TbItem tbItem = new TbItem();
tbItem.setId(killId);
tbItem.setNum(stockNum);
tbItem.setUpdated(new Date());
//更新数据库库存
int res = tbItemMapper.updateByPrimaryKeySelective(tbItem);
if (res > 0 && stockNum >= 0) {
logger.info("购买成功");
result = true;
}
}
}
} finally {
//TODO:释放锁
lock.unlock();
}
return result;
}
5.测试结果
redis:
开20线程,使用JMeter测试
成功5个,失败15
redis库存
数据库库存
6.更多代码请访问我的github:https://github.com/smileLs66/springboot
项目名是:redisson
若发现错误还请各位大佬指正;谢谢
欢迎兴趣的同学一起交流:qq群:1081601635