• 分布式锁3:基于redis的插件redission实现分布式锁


    一  redision简介

    1.1 redission介绍

    Redisson分布式锁是一种基于redis实现的分布式锁,它利用redis的setnx命令实现分布式锁的互斥访问。同时还支持锁的自动续期功能,可以避免因为某个进程崩溃或者网络故障导致锁无法释放的情况。

    只要线程一加锁成功,就会启动一个watchdog看门狗,它是一个后台线程,会每隔10秒检查一下,默认生存时间只有30秒如果线程A还持有锁,那么就会不断的延长锁key的生存时间。可以使用reentracklock,公平锁,读写锁,信号量,闭锁等锁进行加锁操作,完成后然后释放锁。其他线程BCD判断加锁的次数为0,就可以进行加锁操作。

    因此,Redisson就是使用watch dog解决了「锁过期释放,业务没执行完问题。

    如果使用这个分布式锁的Redisson节点实例客户端宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。

    1.2  常用锁介绍

    1.2.1 重入锁

    基于Redis的Redisson分布式可重入锁RLock Java对象实现了java.util.concurrent.locks.Lock接口。 Redisson还通过加锁的方法提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。

    1.2.2 公平锁

    它保证了当多个Redisson客户端线程同时请求加锁时,优先分配给先发出请求的线程。所有请求线程会在一个队列中排队,当某个线程出现宕机时,Redisson会等待5秒后继续下一个线程,也就是说如果前面有5个线程都处于等待状态,那么后面的线程会等待至少25秒。

    1.2.3 联锁

    基于Redis的Redisson分布式联锁RedissonMultiLock对象可以将多个RLock对象关联为一个联锁,每个RLock对象实例可以来自于不同的Redisson实例。要求每一个节点都得满足。则获取锁成功

    1.2.4 redlock 红锁

    基于Redis的Redisson红锁RedissonRedLock对象实现了Redlock介绍的加锁算法。该对象也可以用来将多个RLock对象关联为一个红锁,每个RLock对象实例可以来自于不同的Redisson实例。大部分节点满足则获取锁成功

    1.2.5 信号量

    基于Redis的Redisson的分布式信号量(Semaphore)Java对象RSemaphore采用了与java.util.concurrent.Semaphore相似的接口和用法。同时还提供了异步(Async)反射式(Reactive)RxJava2标准的接口。

    1.2.6 读写锁

    分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态。

    1.2.7 闭锁

    1.3  案例操作

    1.3.1 pom依赖配置

    1.3.2 redisson配置文件

    1. package com.atguigu.distributed.lock.config;
    2. import org.redisson.Redisson;
    3. import org.redisson.api.RedissonClient;
    4. import org.redisson.config.Config;
    5. import org.springframework.context.annotation.Bean;
    6. import org.springframework.context.annotation.Configuration;
    7. /**
    8. * @ClassName: RedissonConfig
    9. * @Description: TODO
    10. * @Author: admin
    11. * @Date: 2024/01/14 23:18:50 
    12. * @Version: V1.0
    13. **/
    14. @Configuration
    15. public class RedissonConfig {
    16. @Bean
    17. public RedissonClient redissonClient(){
    18. Config config = new Config();
    19. // 可以用"rediss://"来启用SSL连接
    20. // config.useSingleServer().setAddress("redis://192.168.43.4:6379");
    21. config.useSingleServer().setAddress("redis://192.168.43.4:6379").setPassword("123456");
    22. return Redisson.create(config);
    23. }
    24. }

    1.3.3  核心加锁代码

    1. @Autowired
    2. private RedissonClient redissonClient;
    3. public void checkAndLockByRedisson() {
    4. // 加锁,获取锁失败重试
    5. RLock lock = this.redissonClient.getLock("rlock");
    6. lock.lock();
    7. System.out.println("redisson的锁....");
    8. // 先查询库存是否充足
    9. Stock stock = this.stockMapper.selectById(1L);
    10. // 再减库存
    11. if (stock != null && stock.getCount() > 0){
    12. stock.setCount(stock.getCount() - 1);
    13. this.stockMapper.updateById(stock);
    14. }
    15. // 释放锁
    16. lock.unlock();
    17. }

    1.3.4  controller调用

    1.3.5  验证调试

    1.启动服务

    2.启动redis

    1. [root@localhost export]# redis-server /myredis/redis.conf
    2. [root@localhost export]# redis-cli -a 123456 -p 6379

    3.启动zk

    1. [root@localhost export]# cd apache-zookeeper-3.7.0-bin/
    2. [root@localhost apache-zookeeper-3.7.0-bin]# cd bin
    3. [root@localhost bin]# ./zkServer.sh start
    4. ZooKeeper JMX enabled by default
    5. Using config: /root/export/apache-zookeeper-3.7.0-bin/bin/../conf/zoo.cfg
    6. Starting zookeeper ... STARTED

    4.启动nginx

    5.启动jemter

    6.查看结果

    2.查看结果

    7.查看db结果

    测试前

    测试后

  • 相关阅读:
    基于Python贝叶斯优化XGBoost算法调参报错“TypeError: ‘float‘ object is not subscriptable”
    超详细图解kafka生产消费流程
    Liunx Mysql安装
    Lidar和IMU(INS)外参标定----常用开源项目总结
    JavaWeb篇_08——Servlet技术以及第一个Servlet案例
    vue2+vite+vue-cli5 实现vite开发webpack打包
    数据结构:反射
    LeetCode刷题系列 -- 172. 阶乘后的零
    题解_notion(持续更新ing)
    react中redux怎么使用
  • 原文地址:https://blog.csdn.net/u011066470/article/details/133780394