【Redisson】分布式锁原理和使用姿势
引言
>Redisson 是让 Redis 摇身一变成为分布式 Java 基础设施的扩展包
文章目录
引言
一、基本配置
1.1 依赖引入
1.2 环境配置
1.3 简单使用
二、分布式锁
2.1 可重入锁原理
2.2 锁重试原理
2.3 看门狗原理
2.4 锁释放原理
2.5 联合锁
一、基本配置
1.1 依赖引入
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency><groupId>org.redisson</groupId><artifactId>redisson-spring-boot-starter</artifactId><version>3.17.7</version>
</dependency>
1.2 环境配置
如果redis是单节点的情况,可以直接结合yml配置的redis配置,无需额外配置。
多节点redis的配置参考如下,有多种选择,这里列举其中一种
@Configuration
public class RedissonConfig {@Beanpublic RedissonClient redissonClient1() {Config config = new Config();config.useSingleServer().setAddress("redis://111.1.184:6379").setPassword("111").setDatabase(0).setConnectionPoolSize(64).setConnectionMinimumIdleSize(10);config.setLockWatchdogTimeout(30_000L);return Redisson.create(config);}}
1.3 简单使用
在配置好环境后就可以进行简单的使用了,这里我们演示通过redisson实现布隆过滤器
// 布隆过滤器private RBloomFilter<Long> shopBloomFilter;/*** 初始化布隆过滤器*/@PostConstructpublic void initRBloomFilter() {CompletableFuture.runAsync(() -> {shopBloomFilter = redissonClient.getBloomFilter(BLOOM_FILTER_SHOP_KEY);int totalCount = this.count();shopBloomFilter.tryInit(totalCount, 0.01);int pageSize = 5000;int loadedCount = 0;// 向上取整int totalPages = (totalCount + pageSize - 1) / pageSize;for (int pageNum = 1; pageNum <= totalPages; pageNum++) {List<Long> shopIds = this.lambdaQuery().select(Shop::getId).page(Page.of(pageNum, pageSize)).getRecords().stream().map(Shop::getId).filter(Objects::nonNull).collect(Collectors.toList());if (CollectionUtils.isEmpty(shopIds)) {log.info("商品布隆过滤缓存完成或暂无数据!");break;}// 将商品ID存储在布隆过滤器里面shopIds.forEach(shopBloomFilter::add);loadedCount += shopIds.size();log.info("布隆过滤器总进度:{}/{}", loadedCount, totalCount);// 最后一页if (shopIds.size() < pageSize) {break;}}log.info("布隆过滤器初始化完成,共加载 {} 个商铺ID", loadedCount);});}
后续在访问redis前先去查询布隆过滤器
@Overridepublic Result queryShopById(Long id) {if (Objects.isNull(id)) {return Result.fail("商品id为空!");}// 防止缓存击穿方案2:布隆过滤器if (!shopBloomFilter.contains(id)) {log.warn("布隆过滤器拦截,商品ID:{}不存在", id);return Result.fail("商品不存在");}return queryWithMutex(id);
// return queryWithExpire(id);}
二、分布式锁
2.1 可重入锁原理
接下来我们探究可重入的实现原理。可重入是指同一个线程可以反复获取,不会卡住自己的互斥锁
下面是基本使用
异步尝试获取锁
核心代码
2.2 锁重试原理
2.3 看门狗原理
看门狗解决业务的处理时间超过了锁过期的时间痛点,解决方案是自动续期。
2.4 锁释放原理
2.5 联合锁
通过给每个redis实例配置一把锁,可以防止当个redis实例宕机的风险,或者改为红锁也是可以的。保证了只需要超过半数获取锁成功就行。