分布式锁-Redisson(一)
一、pom依赖
<!--springboot data redis--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> </dependency> <!-- https://mvnrepository.com/artifact/org.redisson/redisson --> <dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.15.5</version> </dependency>
二、yml文件
spring: redis: host: 127.0.0.1 port: 6379 database: 0 timeout: 1000 password: 961230 lettuce: pool: max-active: 100 max-wait: -1 min-idle: 0 max-idle: 20 ssl: false eureka: client: service-url: defaultZone: http://localhost:7900/eureka/ redisson: address: redis://127.0.0.1:6379 password: 961230 database: 1 timeout: 10000
三、获取 Redisson 配置信息
package com.dongliang.lcnorder.config.lock; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; /** * @author D-L * @version 1.0.0 * @ClassName RedissonProperties.java * @Description 获取 Redisson 配置信息 * @createTime 2021-06-04 23:40:00 */ @ConfigurationProperties(prefix = "redisson") @Data public class RedissonProperties { private int timeout = 3000; private String address; private String password; private int connectionPoolSize = 64; private int connectionMinimumIdleSize = 10; private int slaveConnectionPoolSize = 250; private int masterConnectionPoolSize = 250; private String[] sentinelAddresses; private String masterName; private int database; }
四、自动配置 初始化bean
package com.dongliang.lcnorder.config.lock; import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author D-L * @version 1.0.0 * @ClassName RedissonAutoConfiguration.java * @Description Redisson 自动配置 初始化bean * @createTime 2021-06-04 23:40:00 */ @Configuration @EnableConfigurationProperties(RedissonProperties.class) public class RedissonAutoConfiguration { @Autowired private RedissonProperties properties; @Bean(name = "redissonClient") @ConditionalOnProperty(name = "redisson.address") RedissonClient redissonSingle() { Config config = new Config(); config.useSingleServer().setAddress(properties.getAddress()) .setPassword(properties.getPassword()) .setTimeout(properties.getTimeout()) .setDatabase(properties.getDatabase()) .setConnectionPoolSize(properties.getConnectionPoolSize()) .setConnectionMinimumIdleSize(properties.getConnectionMinimumIdleSize()) .setPingConnectionInterval(60); return Redisson.create(config); } @Bean RedissonDistributedLock distributedLocker() { RedissonDistributedLock distributedLocker = new RedissonDistributedLock(); distributedLocker.setRedissonClient(redissonSingle()); return distributedLocker; } }
五、定义分布式锁工具类
package com.dongliang.lcnorder.config.lock; /** * @author D-L * @version 1.0.0 * @ClassName DistributedLocker.java * @Description * @createTime 2021-06-04 23:40:00 */ public interface DistributedLock { void lock(String entityId); void unlock(String entityId); void lock(String entityId, int timeout); }
package com.dongliang.lcnorder.config.lock; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import java.util.concurrent.TimeUnit; /** * @author D-L * @version 1.0.0 * @ClassName RedissonDistributedLocker.java * @Description * @createTime 2021-06-04 23:40:00 */ public class RedissonDistributedLock implements DistributedLock { private RedissonClient redissonClient; @Override public void lock(String entityId) { RLock lock = redissonClient.getLock(entityId); lock.lock(); } @Override public void unlock(String entityId) { RLock lock = redissonClient.getLock(entityId); if(lock!=null){ if(lock.isLocked() && lock.isHeldByCurrentThread()) { lock.unlock(); } } } @Override public void lock(String entityId, int leaseTime) { RLock lock = redissonClient.getLock(entityId); lock.lock(leaseTime, TimeUnit.SECONDS); } public void setRedissonClient(RedissonClient redissonClient) { this.redissonClient = redissonClient; } }
六、使用
@Autowired private UserDao userDao; @Autowired private DistributedLock Locker; @Override @Transactional(rollbackFor = Exception.class) public void createOrder(TblOrder order) { log.info("createOrder --- beginning:" + order.getOrderName()); if (order == null) { return; } try { //加分布式锁,保证操作幂等性 Locker.lock(order.getOrderName() + order.getUid() + order.getPayType() , 30); //创建订单 buildOrder(order); log.info("createOrder --- success:" + order.getOrderName()); }catch (Exception e) { throw new CustomizeException("createOrder --- error"); }finally { Locker.unlock(order.getOrderName() + order.getUid() + order.getPayType()); } } @Transactional(rollbackFor = Exception.class) protected void buildOrder( TblOrder order) { //构建订单明细并补充订单数据 order.setCreateTime(new Date()); orderDao.insert(order); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } }