步骤:
1、引入依赖
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.13.2</version> </dependency>
2、redisLock配置
yaml配置:
spring:
redis:
database: 0
host: localhost
port: 6379
timeout: 3600
password: 123456
(注:redis未设置password时请注释掉)
redis配置属性绑定:
@Data @Component @ConfigurationProperties(prefix = "spring.redis") public class RedisProperties { private Integer database; private String host; private Integer port; private String password; private Integer timeout;
redisson实例配置
@Configuration @EnableConfigurationProperties(RedisProperties.class) public class ApiConfig { @Bean public RedissonClient redisClient(RedisProperties redisProperties) { Config config = new Config(); String address = "redis://".concat(redisProperties.getHost()).concat(":") .concat(redisProperties.getPort().toString()); config.useSingleServer() .setAddress(address) .setDatabase(redisProperties.getDatabase()) .setPassword(redisProperties.getPassword()); return Redisson.create(config); } }
3、创建RedisLockService类
创建 SampleCallback 接口
public interface SampleCallback<T> { /** * 执行 * * @return T */ T execute(); }
创建 RedisLockService 类
@Service public class RedisLockService { @Autowired private RedissonClient redissonClient; /*** * 可重入锁(Reentrant Lock) * * Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。 * 默认情况下,看门狗检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。 * * @param key 被加锁的key * @param action action * @return T * @author qs * @date 2020/7/10 13:38 * @since 1.0.0 */ public <T> T redisSynchronized(String key, SampleCallback<T> action) { // 获取指定key的锁实例 RLock lock = redissonClient.getLock(key); try { // 加锁,并指定锁过期释放时间 lock.lock(35, TimeUnit.SECONDS); // 执行并返回操作结果 return action.execute(); } finally { // 释放锁 lock.unlock(); } } }
4、创建测试服务
@Service public class AccountServiceImpl implements AccountService { public boolean reducedBalance(Integer uid, Integer number) { return redisLockService.redisSynchronized(RedisKeys.REDIS_LOCK_KEY_PREFIX + uid, () -> { Account account = accountMapper.selectByPrimaryKey(uid); int updateCount = 0; Integer balance = account.getBalance(); if (Objects.nonNull(balance) && balance > Constant.ZERO && account.getBalance() >= number) { account.setBalance(account.getBalance() - number); updateCount = accountMapper.updateByPrimaryKeySelective(account); } return updateCount > 0; }); } }
Account实体类
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
@Data @Table(name = "account") public class Account { @Id @GeneratedValue(generator = "JDBC") private Integer uid; /** * 用户名 */ private String username; /** * 密码 */ private String password; /** * 是否有效(0.有效 1.无效) */ private Short valid; /** * 余额(单位:分) */ private Integer balance;
Dream is not impetuous, but precipitation and accumulation.