SpringCloud Alibaba 之 Config配置中心,Redis分布式锁详解(下)

简介: SpringCloud Alibaba 之 Config配置中心,Redis分布式锁详解(

2.分布式锁

2.1 分布式锁介绍

分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。

在单体的应用开发场景中,在多线程的环境下,涉及并发同步的时候,为了保证一个代码块在同一时间只能由一个线程访问,我们一般可以使用synchronized语法和ReetrantLock去保证,这实际上是本地锁的方式。也就是说,在同一个JVM内部,大家往往采用synchronized或者Lock的方式来解决多线程间的安全问题。但在分布式集群工作的开发场景中,在JVM之间,那么就需要一种更加高级的锁机制,来处理种跨JVM进程之间的线程安全问题.


总之,对于分布式场景,我们可以使用分布式锁,它是控制分布式系统之间互斥访问共享资源的一种方式。比如说在一个分布式系统中,多台机器上部署了多个服务,当客户端一个用户发起一个数据插入请求时,如果没有分布式锁机制保证,那么那多台机器上的多个服务可能进行并发插入操作,导致数据重复插入,对于某些不允许有多余数据的业务来说,这就会造成问题。而分布式锁机制就是为了解决类似这类问题,保证多个服务之间互斥的访问共享资源,如果一个服务抢占了分布式锁,其他服务没获取到锁,就不进行后续操作。如下图:


8f423b21e6494996bf593dd95c90c37b.png


分布式锁要具有一下特征:


互斥性。在任意时刻,只有一个客户端能持有锁。

不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。

具有容错性。只要大部分的 Redis 节点正常运行,客户端就可以加锁和解锁。

解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。


b3f8acd425c74505b925e0ea7b90116a.png


分布式锁的核心是实现多进程之间互斥,而满足这一点的方式有很多,常见的有三种:


a70f9675ba32423f8358e9eb74c335cc.png


2.2 Redisson


Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务,其中就包含了各种分布式锁的实现。


假如我们在微服务架构中,有个订单秒杀服务,要求同一个优惠券,一个用户只能下一单。在单机架构中,我们使用synchronized或者Lock的方式就可以解决这个问题,将查询数据库是否下过单和下单扣减库存过程锁在一块,只允许获得锁的一个线程进行访问。如果不加锁,假如高并发场景下,一百个线程同时访问并且都是同一个用户,然后就会出现多个线程先进行查询操作,如果数据库中没有该订单信息,然后这多个线程就会都符合要求进行下单扣减库存产生多个订单,就会违背一个用户只能下一单的情况。而在分布式中,因为多个服务都是以集群形式的存在存在多个jvm实例,synchronized或者Lock的方式只是针对的同一个JVM内部,这就需要分布式锁。这里使用Redission进行模拟,模拟在微服务集群高并发场景下多个用户线程下下单同一订单扣减库存情况。


2.2.1 Redisson 实践

导入依赖

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

代码如下:


本代码模拟根据订单id查询到订单信息,然后根据订单信息中的goodsId传递到商品微服务,进行对应商品的库存减一,然后返回修改后的商品信息 存储到订单信息对应商品Goods属性上。加分布式锁是保证在同一集群中不同微服务进程中的这个方法只能由获得锁的线程进行处理业务,由于是代码模拟,所以在设计代码的时候相对随意。

    @GetMapping("/order/pay/{id}")
    public Orders1 pay(@PathVariable("id") Long id){
        RLock lock = redissonClient.getLock("lockorder" + id);
        boolean b = lock.tryLock();
        if(!b) {
            return null;
        }
        try {
            Orders1 orders1 = orders1Mapper.selectById(id);
            Goods goods = feign.goodsservice(orders1.getGoodsId());
            orders1.setGoods(goods);
            return orders1;
        }finally {
            lock.unlock();
        }
    }

debug验证结果如下:


下面订单微服务集群为8080端口和9202端口,先访问8080端口,再访问9202端口,在debug环境下验证了我们的猜想。


333e47fc8ce248aeb93a6c404a4886f9.png

81e9223dbdcd45ebb8ed4aa505dd52e9.png



2.2.2 Redisson 原理

此章节引用网上相关描述


Redisson 这个框架对Redis分布式锁的实现原理图如下:


36fa287064ca40c1b9e42bac61b03478.jpg


1.获取锁

一个Redission客户端1要加锁,它首先会根据hash节点选择一台机器,紧接着就会发送一段lua脚本到redis上,比如加锁的那个锁key就是”mylock”,并且设置的时间是30秒,30秒后mylock锁就会被释放。

2.锁互斥机制

如果这个时候Redission客户端2来加锁,它也会会根据hash节点选择一台机器,然后执行了同样的一段lua脚本。

它首先回来判断《mylock》这个锁存在吗?如果存在则Redission客户端2会获得一个数字,这个数字就是mylock这个锁的剩余生存时间。

此时Redission客户端2就会进入到一个while循环,就是CAS不停的自旋尝试加锁,知道成功为止。

3.看门狗机制

如果负责储存这个分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。

为了避免这种情况的发生,Redisson内部提供了一个监控锁的看门狗,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。线程A拿到锁需要处理2秒,但是锁的超时时间只有1秒,也就是说锁超时的时候,业务还没处理完。这时候线程B就进来了又拿到锁,导致加锁跟解锁的时候并不是同一线程。看门狗的作用就是当遇到这种情况的时候,看门狗会定时去查看一下这个线程A是否还在执行任务,如果还在执行则给他继续延长时间。


4.可重入加锁机制

我们知道ReentrantLock是可重入锁,它的特点就是:同一个线程可以重复拿到同一个资源的锁,Redisson也能很好的满足这点。

Redisson客户端1获得mylock锁时,里面会有一个hash结构的数据,如下图所示:

f354228d1b59446eb080c0922883d118.png


5efd4e38ca0047d1a76e13fa5e052510.png



上面这图的意思就是可重入锁的机制,它最大的优点就是相同线程不需要在等待锁,而是可以直接进行相应操作。


5.释放锁机制

如果发现加锁次数变为0了,那么说明这个Redisson客户端1不再持有锁了,Redisson客户端2就可以加锁了。


相关文章
|
机器学习/深度学习 监控 算法
分布式光伏储能系统的优化配置方法(Matlab代码实现)
分布式光伏储能系统的优化配置方法(Matlab代码实现)
583 1
|
存储 缓存 NoSQL
【📕分布式锁通关指南 12】源码剖析redisson如何利用Redis数据结构实现Semaphore和CountDownLatch
本文解析 Redisson 如何通过 Redis 实现分布式信号量(RSemaphore)与倒数闩(RCountDownLatch),利用 Lua 脚本与原子操作保障分布式环境下的同步控制,帮助开发者更好地理解其原理与应用。
934 6
|
存储 负载均衡 NoSQL
【赵渝强老师】Redis Cluster分布式集群
Redis Cluster是Redis的分布式存储解决方案,通过哈希槽(slot)实现数据分片,支持水平扩展,具备高可用性和负载均衡能力,适用于大规模数据场景。
876 2
|
存储 缓存 NoSQL
Redis核心数据结构与分布式锁实现详解
Redis 是高性能键值数据库,支持多种数据结构,如字符串、列表、集合、哈希、有序集合等,广泛用于缓存、消息队列和实时数据处理。本文详解其核心数据结构及分布式锁实现,帮助开发者提升系统性能与并发控制能力。
|
数据采集 存储 数据可视化
分布式爬虫框架Scrapy-Redis实战指南
本文介绍如何使用Scrapy-Redis构建分布式爬虫系统,采集携程平台上热门城市的酒店价格与评价信息。通过代理IP、Cookie和User-Agent设置规避反爬策略,实现高效数据抓取。结合价格动态趋势分析,助力酒店业优化市场策略、提升服务质量。技术架构涵盖Scrapy-Redis核心调度、代理中间件及数据解析存储,提供完整的技术路线图与代码示例。
2122 0
分布式爬虫框架Scrapy-Redis实战指南
|
安全 网络安全 数据库
YashanDB分布式节点间SSL连接配置
本文介绍YashanDB分布式节点间SSL连接配置方法,确保通信安全。需统一为整个集群配置SSL,使用相同根证书签名的服务器证书,否则可能导致连接失败或数据库无法启动。文章详细说明了使用OpenSSL生成根证书、服务器私钥、证书及DH文件的步骤,并指导如何将证书分发至各节点。最后,通过配置数据库参数(如`din_ssl_enable`)并重启集群完成设置。注意,证书过期需重新生成以保障安全性。
|
12月前
|
编解码 运维 算法
【分布式能源选址与定容】光伏、储能双层优化配置接入配电网研究(Matlab代码实现)
【分布式能源选址与定容】光伏、储能双层优化配置接入配电网研究(Matlab代码实现)
895 12
|
NoSQL Java 调度
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
分布式锁是分布式系统中用于同步多节点访问共享资源的机制,防止并发操作带来的冲突。本文介绍了基于Spring Boot和Redis实现分布式锁的技术方案,涵盖锁的获取与释放、Redis配置、服务调度及多实例运行等内容,通过Docker Compose搭建环境,验证了锁的有效性与互斥特性。
1008 0
分布式锁与分布式锁使用 Redis 和 Spring Boot 进行调度锁(不带 ShedLock)
|
数据采集 存储 NoSQL
基于Scrapy-Redis的分布式景点数据爬取与热力图生成
基于Scrapy-Redis的分布式景点数据爬取与热力图生成
1189 67
|
缓存 NoSQL 关系型数据库
Redis缓存和分布式锁
Redis 是一种高性能的键值存储系统,广泛用于缓存、消息队列和内存数据库。其典型应用包括缓解关系型数据库压力,通过缓存热点数据提高查询效率,支持高并发访问。此外,Redis 还可用于实现分布式锁,解决分布式系统中的资源竞争问题。文章还探讨了缓存的更新策略、缓存穿透与雪崩的解决方案,以及 Redlock 算法等关键技术。

热门文章

最新文章