Redis分布式锁红锁

news2024/11/25 4:58:58

Redisson实现分布式锁

lock()上锁解析:
1,hexist判断redis是否有这个锁
2,hset设置锁,hash类型,key为锁名字,value是一对kv,k是当前redisson1的id,v为计数器,表示当前锁持有次数,也就是可重入锁。
3,设置锁默认生存时间为30s
4,采用看门狗策略,开启定时任务每隔10s去检查redisson1所持有的锁是否需要续期,每次续期30s

在这里插入图片描述
unlock()解锁解析:
1,unlock时会将计数器-1
2,当计数器=0时,会触发del操作,删除这个锁。

1,配置类初始化Redisson

@Configuration
public class RedisConfig {
	@Bean
	public Redisson redisson(){
	    //单机模式
	    Config config = new Config();
	    config.useSingleServer().setAddress("ip:port").setDatabase(0);
	    return (Redisson)Redisson.create(config);
	}
}

2,get方法中使用redis分布式锁解决缓存击穿问题

public Product get(Long productId){
    String productCacheKey = RedisKeyPrefixConst.PRODUCT_CACHE+ productId;
    Product product = getProductFromCache(productCacheKey);
    if(product != null){
        return product;
    }
    //加锁
    RLock lock = null;
    try {
        lock = redisson.getLock(productCacheKey);
        lock.lock();
        //双重检测解决缓存击穿问题,当热点缓存失效时,使用分布式锁重新设置缓存
        product = getProductFromCache(productCacheKey);
        if(product!= null){
            return product;
        }

		//有双写不一致问题,在双写不一致问题处解决
        Product product1 = iProductMapper.selectById(productId);
        if(product1!=null){
            //重新设置redis缓存
            redisUtils.set(productCacheKey, product1, AuthConstant.EXPIRATION_TIME_IN_SECOND, TimeUnit.SECONDS);
        }else {
            redisUtils.set(productCacheKey, RedisKeyPrefixConst.PRODUCT_EMPTY_CACHE, AuthConstant.EXPIRATION_TIME_IN_SECOND, TimeUnit.SECONDS);
        }
    } finally {
        lock.unlock();
    }
    return product;

}
private Product getProductFromCache(String productCacheKey) {
    Product product = null;
    Object o = redisUtils.get(productCacheKey);
    if (o!= null){
        if(StringUtils.equals(RedisKeyPrefixConst.PRODUCT_EMPTY_CACHE,o.toString())){
            return new Product();
        }
        product = (Product)o;
    }
    return product;
}

public class RedisKeyPrefixConst {
    public final static String PRODUCT_CACHE = "product:id";
    public final static String PRODUCT_EMPTY_CACHE = "{}";
}

Redis红锁

在Redis的分布式环境中,我们假设有5个Redis master。这些节点完全互相独立,没有主从关系,5个redisson去获取锁,比如执行hset()设置key是lock_name,value中小key是redisson_id redis服务器的id,v是计数器,用于记录锁重入次数。

  • 类似选举投票的机制,设置获取锁时间,和锁持有时间,当超过半数获取锁成功,表示这个锁获取成功。
  • 释放锁时,锁的重入次数-1,如果等于0,就删除当前锁。如果>0说明锁重入了很多次,只-1不,不删除锁。
  • 如果出现异常当超过锁过期时间时,直接删除锁。

1,注册红锁的RedissonClient

@Component
public class RedisConfig {
	@Bean(name = "redissonRed1")
    @Primary
    public RedissonClient redissonRed1(){
        Config config = new Config();
        config.useSingleServer().setAddress("127.0.0.1:6379").setDatabase(0);
        return Redisson.create(config);
    }
    @Bean(name = "redissonRed2")
    public RedissonClient redissonRed2(){
        Config config = new Config();
        config.useSingleServer().setAddress("127.0.0.1:6380").setDatabase(0);
        return Redisson.create(config);
    }
    @Bean(name = "redissonRed3")
    public RedissonClient redissonRed3(){
        Config config = new Config();
        config.useSingleServer().setAddress("127.0.0.1:6381").setDatabase(0);
        return Redisson.create(config);
    }
    @Bean(name = "redissonRed4")
    public RedissonClient redissonRed4(){
        Config config = new Config();
        config.useSingleServer().setAddress("127.0.0.1:6382").setDatabase(0);
        return Redisson.create(config);
    }
    @Bean(name = "redissonRed5")
    public RedissonClient redissonRed5(){
        Config config = new Config();
        config.useSingleServer().setAddress("127.0.0.1:6383").setDatabase(0);
        return Redisson.create(config);
    }
  }

红锁使用

@Service
public class GrabRedisRedissonRedLockLockServiceImpl implements GrabService {
    // 红锁
    @Autowired
    @Qualifier("redissonRed1")
    private RedissonClient redissonRed1;
    @Autowired
    @Qualifier("redissonRed2")
    private RedissonClient redissonRed2;
    @Autowired
    @Qualifier("redissonRed3")
    private RedissonClient redissonRed3;
    @Autowired
    @Qualifier("redissonRed4")
    private RedissonClient redissonRed4;
    @Autowired
    @Qualifier("redissonRed5")
    private RedissonClient redissonRed5;
    @Autowired
	OrderService orderService;

    @Override
    public String grabOrder(int orderId , int driverId){
        System.out.println("红锁实现类");
        //生成key
        String lockKey = ("" + orderId).intern();
        
        //redisson锁 单节点
		//RLock rLock = redissonRed1.getLock(lockKey);
        //红锁 redis son
        RLock rLock1 = redissonRed1.getLock(lockKey);
        RLock rLock2 = redissonRed2.getLock(lockKey);
        RLock rLock3 = redissonRed3.getLock(lockKey);
        RLock rLock4 = redissonRed4.getLock(lockKey);
        RLock rLock5 = redissonRed5.getLock(lockKey);
        RedissonRedLock rLock = new RedissonRedLock(rLock1,rLock2,rLock3,rLock4,rLock5);

        try {

             /**红锁
		     * waitTimeout 尝试获取锁的最大等待时间,超过这个值,则认为获取锁失败
		     * leaseTime   锁的持有时间,超过这个时间锁会自动失效(值应设置为大于业务处理的时间,确保在锁有效期内业务能处理完)
		     */
            boolean b1 = rLock.tryLock((long)waitTimeout, (long)leaseTime, TimeUnit.SECONDS);

            if (b1){
                System.out.println("加锁成功");
                // 此代码默认 设置key 超时时间30秒,过10秒,再延时
                System.out.println("司机:"+driverId+" 执行抢单逻辑");
               
                boolean b = orderService.grab(orderId, driverId);
                if(b) {
                    System.out.println("司机:"+driverId+" 抢单成功");
                }else {
                    System.out.println("司机:"+driverId+" 抢单失败");
                }
                System.out.println("加锁成功");
            }else {
                System.out.println("加锁失败");
            }
        } finally {
        	rLock.unlock();
        }
        return null;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1557715.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【详细讲解语言模型的原理、实战与评估】

🌈个人主页:程序员不想敲代码啊🌈 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家🏆 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提…

【苹果MAC】苹果电脑 LOGI罗技鼠标设置左右切换全屏页面快捷键

首先键盘设置->键盘快捷键 调度中心 设置 f1 f2 为移动一个空间(就可以快捷移动了) 想要鼠标直接控制,就需要下载官方驱动,来设置按键快捷键,触发 F1 F2 安装 LOGI OPTIONS Logi Options 是一款功能强大且便于使用…

HarmonyOS 应用开发之Stage模型绑定FA模型ServiceAbility

本小节介绍Stage模型的两种应用组件如何绑定FA模型ServiceAbility组件。 UIAbility关联访问ServiceAbility UIAbility关联访问ServiceAbility和UIAbility关联访问ServiceExtensionAbility的方式完全相同。 import common from ohos.app.ability.common; import hilog from o…

LabelConvert: 目标检测和图像分割数据集格式转换工具

LabelConvert LabelConvert是一个目标检测和图像分割的数据集格式转换工具,支持labelme、labelImg与YOLO、VOC和COCO 数据集格式之间的相互转换。 支持的转换格式 安装 pip install label_convert具体使用方法 由于文章篇幅所限,请移步LabelConvert官…

Linux初学(十一)中间件

一、web服务 1.1 中间件简介 中间件其实就是一类软件,中间件的作用是让用户可以看到一个网页 总结:客户端可以向服务端发送请求,服务器端会通过中间件程序来接收请求,然后处理请求,最后将处理结果返回给客户端 1.2 中…

【MySql数据库】MySQL5.7在navicat中建立连接报错1045及重装MySQL过程中3306端口号被占用释放的过程

文章目录 一、报错1、软件中报错2、navicat中报错3、数据库密码是正确的4、卸载数据库5、重装数据库发现3306端口被占用 二、释放3306端口1、找到3306端口对应的PID值2、释放3306端口号3、释放端口后,重装数据库 一、报错 1、软件中报错 2、navicat中报错 在navic…

cocos2.x => node 属性修改

简介 与节点属性相关的几个核心变量_trs、_matrix、_worldMatrix、_localMatDirty、_worldMatDirty。 _trs:存储节点的position、rotation、scale _matrix:存储节点的缩放、位移、旋转三者合一的变化矩陈(仿射矩陈) _worldMat…

linux基础命令篇:Linux基础命令讲解——文件浏览(cat、less、head、tail和grep)

Linux基础命令讲解——文件浏览(cat、less、head、tail和grep) 本文详细介绍Linux中的cat、less、head、tail和grep命令,这些命令在日常工作中非常实用,以下是关于这些命令的详细介绍: 1. cat命令:用于查看…

简明Pytorch分布式训练 — DistributedDataParallel 实践

上一次的Pytorch单机多卡训练主要介绍了Pytorch里分布式训练的基本原理,DP和DDP的大致过程,以及二者的区别,并分别写了一个小样作为参考。小样毕竟还是忽略了很多细节和工程实践时的一些处理方式的。实践出真知,今天(简…

每日面经分享(http、python)

1. http和HTTPS的区别,http的响应流程 a. 区别: i. 安全性:HTTP是明文传输数据,不提供加密保护,因此数据容易被窃听和篡改。而HTTPS使用SSL/TLS协议对数据进行加密和身份验证,提供更高的安全性。 ii. 端口…

新网站秒收录技术,新网站百度收录时间

在建立新网站后,让它尽快被搜索引擎收录是网站主最为关注的事情之一。百度作为中国最大的搜索引擎,网站被其快速收录对于增加曝光和流量至关重要。本文将介绍一些新网站秒收录技术,以及一般情况下新网站被百度收录需要的时间。 新网站秒收录技…

百度资源平台链接提交

百度资源平台是百度搜索引擎提供的一个重要工具,用于帮助网站主将自己的网站链接提交给百度搜索引擎,以便更快地被收录和展示在搜索结果中。以下将就百度资源平台链接提交的概念、操作方法以及其对网站收录和曝光的影响进行探讨: 什么是百度资…

docker-compose安装jenkins

1、环境准备:准备安装好docker的服务器一台 2、在服务器上创建一个目录用于安装Jenkins mkdir jenkins3、下载好要挂载的:maven、jkd;并将下载好的tar.gz包上传至服务器待安装目录中并解压 tar -xzvf tar -xzvf apache-maven-3.9.6-bin.tar…

最短路-Floyd Dijkstrea

Floyd算法 一种求解“多源最短路”问题的算法 在Floyd算法中,图一般用邻接矩阵存储,边权可正可负(但不允许负环),利用动态规划的思想,逐步求解出任意两点之间的最短距离 int d[N][N],初始为无穷 d[i][j…

生信数据分析——GO+KEGG富集分析

生信数据分析——GOKEGG富集分析 目录 生信数据分析——GOKEGG富集分析1. 富集分析基础知识2. GO富集分析(Rstudio)3. KEGG富集分析(Rstudio) 1. 富集分析基础知识 1.1 为什么要做功能富集分析? 转录组学数据得到的基…

设计模式6--抽象工厂模式

定义 案例一 案例二 优缺点

【2023】kafka入门学习与使用(kafka-2)

目录💻 一、基本介绍1、产生背景2、 消息队列介绍2.1、消息队列的本质作用2.2、消息队列的使用场景2.3、消息队列的两种模式2.4、消息队列选型: 二、kafka组件1、核心组件概念2、架构3、基本使用3.1、消费消息3.2、单播和多播消息的实现 4、主题和分区4.…

QT:如何在程序密集响应时,界面不会卡住?

前因: 当调用QApplication::exec()时,就启动了QT的事件循环。在开始的时候QT会发出一些事件命令来显示和绘制窗口部件。 在这之后,事件循环就开始运行,它不断检查是否有事件发生并且把这些事件发生给应用程序的QObject。 当处理…

HarmonyOS 应用开发之FA模型绑定Stage模型ServiceExtensionAbility

本文介绍FA模型的三种应用组件如何绑定Stage模型的ServiceExtensionAbility组件。 PageAbility关联访问ServiceExtensionAbility PageAbility关联访问ServiceExtensionAbility和PageAbility关联访问ServiceAbility的方式完全相同。 import featureAbility from ohos.ability…

Git 核心知识

2024年3月30日 Git 安装 官网下载,Git 选择合适的版本,无脑下一步即可。 安装成功之后,鼠标右键任意的文件夹,会出现 Git GUI 的选项,即安装成功 安装注意事项 安装前,检查环境变量 , 如果…