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

分布式锁详解

1.分布式锁需要满足的要求

  • 加锁与释放锁都是原子的
  • 共享存储系统保存了锁变量,因此共享存储系统要保证自身的可靠性

2. redis分布式锁

2.1. set key方式实现分布式锁

2.1.1 实现原理

SET key value [EX seconds | PX milliseconds]  [NX | XX]
  • EX seconds:设置键的过期时间,单位为秒。

  • PX milliseconds:设置键的过期时间,单位为毫秒。

  • NX:只有当键不存在时,才对键进行设置操作。

  • XX:只有当键已经存在时,才对键进行设置操作

// 加锁, unique_value作为客户端唯一性的标识
SET lock_key  unique_value EX 20 NX


 设置一个key为lock_key,value为unique_value 的锁,有效时间20秒,
且当锁之前不存在时才能加锁成功

过期时间保证了:即便解锁失败,也不会长期占用

2.1.2 存在问题

  • 自动续期问题
  • 重入性问题

2.1.3 该进

解决续期问题

待续......

2.1.4 spring boot集成

2.2. redission提供的分布式锁

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

2.2.1 实现代码

import org.redisson.Redisson;   
import org.redisson.api.RLock;   
import org.redisson.config.Config;
   
public class CacheBreakthrough {
    private static final String KEY = "lock_test";
    private static final Redisson redisson;
 
    static {
        Config config = new Config();
        config.useSingleServer().setAddress("redis://127.0.0.1:6379");
        redisson = Redisson.create(config);
    }
 
    public static Object lockTest() {
            RLock lock = redisson.getLock(KEY);
            try {
                检测重入性
                lock.lock();
                lock.lock();
                lock.lock();
            }finally{
                lock.unlock();
                lock.unlock();
                lock.unlock();
                }
     }

2.2.2 redis储存形式

使用hash结构存储

锁的默认30秒的有效期,自动续期时间10秒会检测一次任务是否完成,如果未完成,自动续期

2.2.3 如何实现可重入的

使用hash结构存储,key为锁名称key

hash中元素只有1个键值对,且key为当前线程标识,value为加锁次数,默认为1。

2.2.4 如何实现自动续期

  1. 看门狗机制:当一个线程获取到锁时,Redisson 会启动一个看门狗后台线程。该线程会定期检查当前线程是否仍然持有锁,如果是,则不断延长锁的生存时间。

  2. 默认续期时间:Redisson 的锁自动续期默认时间是 30 秒,这个时间是可以被修改的。

  3. 续期操作:看门狗线程每间隔一定时间(默认为 30 秒的一半即 15 秒)检查当前线程是否仍然持有锁,如果是则延长锁的过期时间。

2.2.4.1 注意事项
  1. 自动续期条件:只有当使用 lock() 方法获取锁时,Redisson 才会自动续期。如果使用 lock(long leaseTime, TimeUnit unit) 方法指定锁的过期时间,则不会自动续期

  2. 手动续期:在某些情况下,如果业务逻辑非常复杂,可能需要手动续期。可以使用 lock.expire 方法手动延长锁的过期时间。

2.2.4.2 看门狗实现的原理

       起一个后台线程,定时查看要续期的key是否存在,如果存在,则表示还在处理业务,需要续期,然后使用expireTime修改key的过期时间

(未完.....)

3. mysql分布式锁

利用唯一索引的特性

3.1 简单的设计

3.1.1 实现原理

id,

lock_key: 唯一索引,由业务生成唯一标识作为锁

expire_time: 过期时间(启动一个后台线程扫描过期的key,然后删除,避免“释放锁失败导致的不会过期”)

当插入数据失败时,则表示加锁失败

3.1.2 存在问题

  • 重入性
  • 被其他事务释放
  • 不会自动过期

3.2 复杂的设计

表字段:

id

lock_key:  唯一索引,由业务生成唯一标识作为锁

thread_id:  结合加锁的线程生成唯一的标识,避免被其他线程解锁

lock_num: 重入的次数(默认1,加锁时,先判断当前lock_key是否存在,如果存在则验证thread_id:  如果通过,则把lock_num+1)

expire_time: 过期时间(启动一个后台线程扫描过期的key,然后删除,避免“释放锁失败导致的不会过期”)

4. zookeeper分布式锁

未用过

5. 结论

经常使用redission提供的redis锁;

非高并发业务,也可使用mysql分布式锁的简单设计方案(一个业务,很少有需要重入锁的情况)


http://www.kler.cn/a/510269.html

相关文章:

  • 【LLM-RL】DeepSeekMath强化对齐之GRPO算法
  • Linux 操作二:文件映射与文件状态
  • SimpleHelp远程管理软件存在任意文件读取漏洞(CVE-2024-57727)
  • Net Core微服务入门全纪录(三)——Consul-服务注册与发现(下)
  • 【深入解析】 RNN 算法:原理、应用与实现
  • 19. C语言 共用体(Union)详解
  • 从零开始学数据库 day2 DML
  • G1原理—7.G1的GC日志分析解读
  • python+django+Nacos实现配置动态更新-集中管理配置(实现mysql配置动态读取及动态更新)
  • Node.js 与 JavaScript 是什么关系
  • 47,【5】BUUCTF web lovesql
  • 联德胜w801开发板(四)实现腾讯云mqtt的订阅和发布
  • 浅谈 JVM
  • Gitlab Runner安装与配置
  • mkv转码mp4(ffmpeg工具)
  • 寒假1.18
  • VUE学习笔记(入门)4__安装开发者工具
  • ElasticSearch上
  • 51.WPF应用加图标指南 C#例子 WPF例子
  • Node.js path.resolve
  • clang、C++23标准库模块基本使用
  • Vue如何构建项目
  • go采集注册表
  • imread和jpeg_read在MATLAB中处理图像时的不同
  • 1.17组会汇报
  • windows-本地部署Git仓库-安装Gitea