栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring Boot Redis 实现分布式锁,真香,你掌握了多少?

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring Boot Redis 实现分布式锁,真香,你掌握了多少?

org.springframework.boot

spring-boot-starter-integration

org.springframework.integration

spring-integration-redis

Spring Boot 基础知识就不介绍了。

配置分布式锁

@Bean(destroyMethod = “destroy”)

public RedisLockRegistry redisLockRegistry(RedisConnectionFactory redisConnectionFactory) {

return new RedisLockRegistry(redisConnectionFactory, “lock”);

}

使用示例

@GetMapping("/redis/lock")

public String lock(@RequestParam(“key”) String key) {

for (int i = 0; i < 10; i++) {

new Thread(() -> {

redisLockService.lock(key);            try {

Thread.sleep(3000L);

} catch (InterruptedException e) {

e.printStackTrace();            }            System.out.println(DateFormatUtils.format(new Date(), “yyyy-MM-dd HH:mm:ss”));

redisLockService.unlock(key);        }        ).start();    }    return “OK”;

}

RedisLockService 是我封装了的一个 Redis 锁服务,代码有点多,这里就不贴了,完整的代码示例在 Github 上,大家可以 Star 一下:

https://github.com/javastacks/spring-boot-best-practice

测试:

http://localhost:8080/redis/lock?key=yeah

输出:

2020-06-23 11:15:34

2020-06-23 11:15:37

2020-06-23 11:15:40

2020-06-23 11:15:43

2020-06-23 11:15:46

2020-06-23 11:15:49

2020-06-23 11:15:52

2020-06-23 11:15:55

2020-06-23 11:15:58

2020-06-23 11:16:01

可以看到每个线程需要等上一个线程休眠 3 秒后才能获取到锁。

源码分析


集成完了,会使用了,还得研究下 RedisLockRegistry 的源码,不然遇到什么坑还得再踩一遍。

RedisLockRegistry 有两个类构造器:

  • connectionFactory:Redis 连接工厂

  • registryKey:锁前缀

  • expireAfter:失效时间(非必须项,

《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》

【docs.qq.com/doc/DSmxTbFJ1cmN1R2dB】 完整内容开源分享

默认60秒)

所以,我们要注册 expireAfter 这个选项,默认 60 秒是否满足业务需要,如果超过默认的 60 少时间,否则将导致锁失效。

还有两个和 RedisLockRegistry 相关且很重要的成员变量:

private final String clientId = UUID.randomUUID().toString();

private final Map locks = new ConcurrentHashMap<>();

  • clientId:

首先用来标识当前 RedisLockRegistry 实例ID,并且在设置、移除锁的时候都会要用到,用来判断是不是当前的锁注册实例。

  • locks:

用来在内存中缓存当前锁注册实例所有锁对象。

获取锁对象

如下面获取锁对象源码所示:

每个 key 在内存中(ConcurrentHashMap)都对应一个锁对象,锁对象有生成过就直接返回,没有就生成再返回,有了这个锁对象才能进行上锁和解锁操作。

这个锁对象(RedisLock)其实也是实现了 Java 中的 java.util.concurrent.locks.Lock 锁接口:

锁对象(RedisLock)也有两个很重要的成员变量:

private final ReentrantLock localLock = new ReentrantLock();

private volatile long lockedAt;

  • localLock:

localLock 是一个本地内存可重入锁,每次去 Redis 上锁前,都要用本地 localLock 上锁先,这样能做到尽可能的少往 Redis 上锁,也能从一方面提升锁的性能。

  • lockedAt:

lockedAt 上锁时间,移除过时锁会用到。

阻塞上锁

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/605472.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号