赞
踩
分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。
分布式锁的核心是实现多进程之间互斥,而满足这一点的方式有很多,常见的有三种:
原理:利用setnx的互斥性;利用ex避免死锁;释放锁时判断线程标示 缺陷:不可重入、无法重试、锁超时失效
实现分布式锁时需要实现的两个基本方法:
互斥:确保只能有一个线程获取锁
# 释放锁,删除即可
DEL key
分布式锁实现,满足:
在获取锁时存入线程标示(可以用UUID表示)
在释放锁时先获取锁中的线程标示,判断是否与当前线程标示一致
如果一致则释放锁
如果不一致则不释放锁
https://github.com/redisson/redisson
原理:利用hash结构,记录线程标示和重入次数;利用watchDog延续锁时间;利用信号量控制锁重试等待
缺陷:redis宕机引起锁失效问题
依赖
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.13.6</version>
</dependency>
配置Redisson客户端:
import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RedisConfig { @Bean public RedissonClient redisClient() { Config config = new Config(); config.useSingleServer().setAddress("redis://47.96.16.107:6379").setPassword("654321"); return Redisson.create(config); } }
使用
@Resource private RedissonClient redissonClient; @Test void testRedisson() throws InterruptedException { // 获取锁(可重入),指定锁的名称 RLock lock = redissonClient.getLock("anyLock"); // 尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位 boolean isLock = lock.tryLock(1, 10, TimeUnit.SECONDS); // 判断释放获取成功 if (isLock) { try { System.out.println("执行业务"); } finally { // 释放锁 lock.unlock(); } } }
配置类
import org.redisson.Redisson; import org.redisson.api.RedissonClient; import org.redisson.config.Config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RedisConfig { @Bean public RedissonClient redisClient1() { Config config = new Config(); config.useSingleServer().setAddress("redis://47.96.16.107:6379").setPassword("654321"); return Redisson.create(config); } @Bean public RedissonClient redisClient2() { Config config = new Config(); config.useSingleServer().setAddress("redis://47.96.16.107:6380").setPassword("654321"); return Redisson.create(config); } @Bean public RedissonClient redisClient3() { Config config = new Config(); config.useSingleServer().setAddress("redis://47.96.16.107:6381").setPassword("654321"); return Redisson.create(config); } }
multiLock
import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.redisson.api.RLock; import org.redisson.api.RedissonClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import javax.annotation.Resource; import java.util.concurrent.TimeUnit; @Slf4j @SpringBootTest class SimpleLockTest { @Resource private RedissonClient redissonClient1; @Resource private RedissonClient redissonClient2; @Resource private RedissonClient redissonClient3; @Test void testRedisson() throws InterruptedException { RLock lock1 = redissonClient1.getLock("apple"); RLock lock2 = redissonClient2.getLock("apple"); RLock lock3 = redissonClient3.getLock("apple"); RLock lock = redissonClient1.getMultiLock(lock1, lock2, lock3); // // 获取锁(可重入),指定锁的名称 // RLock lock = redissonClient.getLock("anyLock"); // 尝试获取锁,参数分别是:获取锁的最大等待时间(期间会重试),锁自动释放时间,时间单位 boolean isLock = lock.tryLock(1, 10, TimeUnit.SECONDS); // 判断释放获取成功 if (isLock) { try { System.out.println("执行业务"); } finally { // 释放锁 lock.unlock(); } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。