当前位置: 首页 > news >正文

Redisson 实现分布式锁

        在平常的开发工作中,我们经常会用到锁,那么锁有什么用呢?锁主要是控制对共享资源的访问顺序,防止多个线程并发操作导致数据不一致的问题。经常可能会听到乐观锁、悲观锁、分布式锁、行锁、表锁等等,那么我们今天总结下分布式锁的实现方式之Redisson。

     一:概述

        提到分布式锁,我们先说说什么是锁?锁就是为了避免多个线程同时访问某个共享资源时,修改了数据,导致出现数据一致性。锁好比一个房间只能进去一个人办理事情,得等里面的人出来,其他人才能进去。那么什么是分布式锁呢?分布式锁就是在分布式项目中使用的锁。说到这儿,那就说说什么是分布式。分布式系统是指由多个节点、通过网络连接,共同完成任务的系统。如一个系统由用户服务、订单服务、支付服务、仓储服务等组成,之间通过网络通信调用,那么就是分布式系统。

     二:分布式锁特点

        1:互斥性:同一时刻只有一个客户端(进程或线程)能够持有锁。
        2:可重入性:同一个客户端在已经持有锁的情况下,可以再次获取该锁而不会被阻塞。
        3:容错性:如客户端崩溃、网络中断等。当客户端在持有锁的过程中出现异常崩溃时,锁能够自动释放,避免出现死锁的情况。
        4:高可用:有良好的获取锁与释放锁的功能,避免分布式锁失效。

    三:分布式锁应用场景

       1:电商系统中秒杀、库存扣减,防止超卖。
       2:分布式任务执行,先获取锁,再执行任务,保证数据一致性。
       3:分布式系统幂等,如支付回调、消息消费等。

     四:代码实现

     1:引入依赖

<dependency>
    <groupId>org.redisson</groupId>
    <artifactId>redisson</artifactId>
    <version>3.18.0</version>
</dependency>

     2:application.yml  redis 配置

  data:
    redis:
      # 连接地址
      host: 127.0.0.1
      # 端口
      port: 6379
      # 数据库
      database: 0
      # 用户名
      # username: redis
      # 密码
      password: 123456
      # 连接超时
      connect-timeout: 5s
      # 读超时
      timeout: 30s

      3:RedissonConfig

        RedissonConfig 主要作用是对 Redisson 客户端进行配置和初始化。

import org.redisson.Redisson;
import org.springframework.beans.factory.annotation.Value;
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 RedissonConfig {

    @Value("${spring.data.redis.host}")
    private String redisHost;

    @Value("${spring.data.redis.port}")
    private int redisPort;

    @Value("${spring.data.redis.password}")
    private String password;

    @Value("${spring.data.redis.database}")
    private int database;

    @Bean
    public RedissonClient redissonClient() {
        Config config = new Config();
        config.useSingleServer()
              .setAddress("redis://" + redisHost + ":" + redisPort)
              .setDatabase(database)
              .setPassword(password);
        return Redisson.create(config);
    }

      4:锁实现

import cn.hutool.extra.spring.SpringUtil;
import com.ruoyi.system.service.ILockforService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 商品实现类
 */
@Service
@Slf4j
public class SysLockforServiceImpl implements ILockforService{

    @Resource
    private RedissonClient redissonClient;

    @Override
    public void addGoods() {
        // 定义锁的键
        String lockKey = "addGoodsLock";
        // 获取分布式锁实例
        // 如果在静态方法中,无法注入,通过如下获取 bean
        //RedissonClient redissonClient = SpringUtil.getBean(RedissonClient.class);
        RLock lock = redissonClient.getLock(lockKey);
        try {
            // 尝试获取锁,等待 1 秒,锁的过期时间为 1 秒
            boolean isLocked1 = lock.tryLock(1, 5, TimeUnit.SECONDS);
            // 尝试获取锁,等待 0 秒,即没有获取到会立即返回,没有设置锁的过期时间,则不会自动释放锁,释放锁需要手动控制
            // boolean isLocked2 = lock.tryLock(0, TimeUnit.SECONDS);
            if (!isLocked1) {
                log.info("未获取到锁,请稍后再试!");
            }
            // 模拟业务逻辑
            log.info("开始处理业务");
            log.info("处理业务结束");
        } catch (Exception e) {
            log.error("新增商品异常", e);
        } finally {
            // 释放锁
            lock.unlock();
        }
    }

      5:锁的过期时间

        如果设置了过期时间,在到达过期时间后,锁会释放。如果未设置锁的过期时间,则需要在代码中手动释放锁。
        如果持有锁的客户端在获取锁之后发生异常关闭(例如程序崩溃、服务器宕机等),由于 Redisson 底层是基于 Redis 实现的,Redis 中存储的锁键值对可能会一直存在,导致其他客户端无法获取该锁,形成死锁。不过,Redisson 为了避免这种情况,有一个看门狗(Watchdog)机制。
        看门狗机制会在客户端获取锁时自动为锁设置一个默认的过期时间(默认是 30 秒),并且会在后台启动一个定时任务,不断地延长锁的过期时间,只要客户端还持有锁且没有手动释放。但如果客户端异常关闭,定时任务无法继续执行,锁会在过期时间到达后自动释放。
        正常情况下使用 tryLock(0, TimeUnit.SECONDS) 需要手动释放锁,但在客户端异常关闭的情况下,看门狗机制会保证锁最终能够自动释放。

     五:总结

        实现 Redisson 分布式锁,主要是引入依赖,在 application.yml 中配置 redis 连接信息,配置 RedissonConfig,实现分布式锁。

        可能遇到的问题,如果未配置 RedissonConfig,则会注入异常,如下:

        以上为 Redisson 实现分布式锁的主要步骤。

相关文章:

  • Flask返回文件方法详解
  • 急速实现Anaconda/Miniforge虚拟环境的克隆和迁移
  • SpringCloud微服务(一)Eureka+Nacos
  • ADGaussian:用于自动驾驶的多模态输入泛化GS方法
  • AI与大数据融合:技术全景、行业实践与前沿趋势(2025版)
  • Python监控网站更新则推送到企业微信
  • 生产事故:Undertow容器的xnio线程引发CPU100%的方案验证后续(二)
  • Spring MVC与Spring Boot文件上传配置差异对比及文件上传关键类详细说明与对比
  • 【小沐杂货铺】基于Three.JS绘制太阳系Solar System(GIS 、WebGL、vue、react,提供全部源代码)
  • 谈Linux之磁盘管理——万字详解
  • CMDB平台(进阶篇):机房拓扑功能深度解析
  • css使用mix-blend-mode的值difference实现内容和父节点反色
  • redis的数据类型(1)
  • 12、主频和时钟配置实验
  • PhotoShop学习06
  • SpringBoot学生评奖评优管理系统的设计与实现
  • SpringBoot3笔记
  • C++中如何比较两个字符串的大小--compare()函数实现
  • 空对象模式(Null Object Pattern)在C#中的实现详解
  • 【区块链+ 人才服务】北京师范大学区块链底层链平台 | FISCO BCOS 应用案例
  • 建设银行官网招聘网站/摘抄一篇新闻
  • 建设部网站为什么打不开/竞价托管外包服务
  • 贺州做网站/手机网站百度关键词排名
  • 百度怎么自己做网站/推广网站最有效办法
  • 无锡网站制作难吗/疫情防控数据
  • 如何跟进网站建设的客户/班级优化大师免费下载电脑版