【Redis】Redisson 基础和快速入门

一、setnx 实现的分布式锁的问题

我们之前介绍了使用 setnx 实现分布式锁,但是其含有如下问题:

  • 不可重入:同一个线程无法多次获取同一把锁
  • 不可重试:获取锁只产生一次
  • 超时释放:业务执行时间过长导致锁释放,存在安全隐患
  • 主从一致性:主从同步延迟导致安全问题 (正常不会出现,主从同步很快)

二、Redisson 是什么

Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务。其中包括(BitSet, Set, Multimap, SortedSet, Map, List, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, AtomicLong, CountDownLatch, Publish / Subscribe, Bloom filter, Remote service, Spring cache, Executor service, Live Object service, Scheduler service) Redisson提供了使用Redis的最简单和最便捷的方法。Redisson的宗旨是促进使用者对Redis的关注分离(Separation of Concern),从而让使用者能够将精力更集中地放在处理业务逻辑上。

翻译: Redisson 就是一个 Redis 框架,帮我们实现一些功能

https://github.com/redisson/redisson/wiki/%E7%9B%AE%E5%BD%95

三、SpringBoot 整合 Redission

  1. 导入依赖
   <!-- https://mvnrepository.com/artifact/org.redisson/redisson -->
   <dependency>
       <groupId>org.redisson</groupId>
       <artifactId>redisson</artifactId>
       <version>3.13.6</version>
   </dependency>
  1. 配置 Redisson

不推荐使用 SpringBoot 提供 的Starter 的方式,会替代 Spring 官方的 Redis 实现

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;
/**
 * @Author: WanqingLiu
 * @Date: 2022/12/10/16:25
 */
@Configuration
public class RedisConfig {
    @Bean
    public RedissonClient redissonClient(){
        // 配置类
        Config config = new Config();
        // 设置 redis 地址
        config.useSingleServer().setAddress("redis:// 192.168.244.130:6379");
        // 返回
        return Redisson.create(config);
    }
}
  1. 注入使用 RedissonClient

使用模板:

在这里插入图片描述

业务代码:

@Service
public class ServiceImpl  {


	// 注入 RedissonClient
    @Resource
    private RedissonClient redissonClient;

    @Override
    public Result testRedissonClient(Long voucherId) {

        // ****** 获取锁 *******
        RLock rLock = redissonClient.getLock("lock:order:" + userId);
        boolean isLock = rLock.tryLock();
		// **** 获取锁失败提示 *****
        if (!isLock){
            return Result.fail("提升获取锁失败");
        }

        try {
        	// 执行业务
           createVoucherOrder(voucherId); 
        } finally {
            // ******** 释放锁 *********
            rLock.unlock();
        }
    }

    @Transactional
    // 实现一人一单 —— 悲观锁 —— 以用户 id 加锁 —— 处理同一个用户的并发安全问题,防止一个用户并发买很多单
    public Result createVoucherOrder(Long voucherId){
	// 业务代码
}

四、Redisson 实现 可重入锁原理

使用 Hash 结构记录线程id 和 线程重录次数

在这里插入图片描述

  • 获取锁:每次相同线程获取锁重录次数 + 1

    获取锁的 Lua 脚本如下:

在这里插入图片描述

  • 释放锁:把重入次数减 1,当可重入次数为 0 时,删除锁

    释放锁的 Lua 脚本如下:

在这里插入图片描述

五、Redisson 锁重试和 WatchDog 机制

在这里插入图片描述

  • 可重试实现思路:利用信号量和订阅者功能实现等待、唤醒,获取锁失败重试机制

Redisson 锁重试关键源码注释:

在这里插入图片描述

  • 超时延续实现思路:利用 watchdog 看门狗机制,每隔一段时间 (releaseTime / 3), 重置超时时间

WatchDog 机制关键源码注释:

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值