redis分布式锁到redisson的转变
首先导入redis依赖:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency>
然后配置redis:
spring: redis: host: 192.168.1.210 port: 6379
使用redis实现分布式主体代码:
@Autowired StringRedisTemplate redisTemplate; public String getDistributeResult() { //1.占分布式锁 String uuid = UUID.randomUUID().toString(); Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uuid, 300, TimeUnit.SECONDS);//保证锁的赋值和过期时间设置的原子性,同时过期时间避免出现死锁问题 if(lock){ System.out.println("获取分布式锁成功。。。"); //加锁成功...执行业务 String result = ""; try{ result = getResult(); }finally{ String script = "if redis.call(get, KEYS[1]) == ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end"; //删除锁 Long lock1 = redisTemplate.execute(new DefaultRedisScript<Long>(script, Long.class), Arrays.asList("lock"), uuid); } return result; }else{ try { //休眠100ms重试 Thread.sleep(200); } catch (InterruptedException e) { } return getDistributeResult();//自旋方式 } } public String getResult(){ return "ok"; }
lua脚本解锁(获取值并进行对比)也是为了避免客户端在过期时间后尝试释放锁,删除稍后获得锁的另一个客户端创建的,参考:
开发中经常会使用redisson代替上面繁琐的(容易遗漏的)分布式锁实现,大量节省了开发时间,让程序员把更多的精力放在业务开发上。
想要使用redisson首先要引入依赖(redis的也需要前面已经引入过了)
<dependency> <groupId>org.redisson</groupId> <artifactId>redisson</artifactId> <version>3.12.0</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; import java.io.IOException; @Configuration public class MyRedissonConfig { @Bean public RedissonClient redisson() throws IOException { //1.创建配置 Config config = new Config(); config.useSingleServer().setAddress("redis://192.168.1.210:6379"); RedissonClient redissonClient = Redisson.create(config); return redissonClient; } }
然后就可以使用redisson了,如下:
@Autowired RedissonClient redisson; public String getResultWithRedissonLock() { RLock lock = redisson.getLock("redisson-lock"); lock.lock(); String result = ""; try{ result = getResult(); }finally{ lock.unlock(); } return result; }
lock()加锁,unlock()释放锁,就是这么简单。
redisson的锁默认过期时间30s(LockWatchdogTimeout看门狗的默认时间),且支持自动续期(即业务执行未完成可以延长锁的过期时间),只要占锁成功,就会启动一个定时任务【重新给锁设置过期时间,新的过期时间就是看门狗的默认时间】,每隔10s(internalLockLeaseTime【看门狗时间】 / 3, 10s)都会自动再次续期,续成30s
如果我们设置了过期时间,那么就不会存在自动续期等操作,
lock.lock(10, TimeUnit.SECONDS);但是一定要保证自动解锁的时间要大于业务执行的时间。
同时redisson还支持多种锁机制,包含RReadWriteLock,RSemaphore,RCountDownLatch等
可以根据自己的业务场景使用不同的锁。