简单认识redis - 12 redis锁

体样式**redis中,不同的问题有不一样的解决办法,那么锁也有不同的锁来解决不一样的问题,下面将举出几个常用的redis锁。

1. SETNX锁(简单独占锁)

  • 原理
    • SETNX(SET if Not eXists)是Redis实现简单锁的命令。它的操作是原子性的,当尝试设置一个键值对时,如果键不存在,则设置成功并返回1,表示获取锁成功;如果键已经存在,则返回0,表示锁已被其他客户端占用。
  • 示例
    • 假设使用lock_key作为锁的键,locked_value作为锁的值,在Java中可以这样实现:
      import redis.clients.jedis.Jedis;public class SimpleRedisLock {public static void main(String[] args) {Jedis jedis = new Jedis("localhost", 6379);String lock_key = "my_lock";String locked_value = "locked";long result = jedis.setnx(lock_key, locked_value);if (result == 1) {System.out.println("获取锁成功");// 执行业务逻辑try {// 模拟业务逻辑执行时间Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}// 释放锁,这里简单地删除键jedis.del(lock_key);} else {System.out.println("获取锁失败");}jedis.close();}
      }
      
  • 局限性
    • 没有自动释放机制。如果获取锁的客户端崩溃或者出现异常没有执行释放锁的操作,这个锁将一直被占用,导致死锁。

2. 带有过期时间的SET锁

  • 原理
    • Redis的SET命令可以在设置键值对的同时设置过期时间,并且这个操作是原子性的。例如,SET key value EX seconds NX这样的命令格式,其中EX seconds表示设置过期时间为seconds秒,NX表示只有当键不存在时才设置。
  • 示例
    • 在Python中,可以这样实现:
      import redis
      import timer = redis.Redis(host='localhost', port=6379)
      lock_key = "my_lock"
      locked_value = "locked"
      expire_time = 10
      result = r.set(lock_key, locked_value, ex=expire_time, nx=True)
      if result:print("获取锁成功")try:# 执行业务逻辑time.sleep(7)finally:# 不需要手动删除锁,过期后自动释放pass
      else:print("获取锁失败")
      
  • 注意事项
    • 业务逻辑执行时间如果超过了锁的过期时间,可能会出现数据不一致的情况。例如,在锁过期后,其他客户端获取了锁,然后原来的客户端完成业务逻辑并释放锁,这可能会导致新获取锁的客户端的操作受到干扰。

3. RedLock(分布式锁算法)

  • 原理
    • RedLock算法用于在多个Redis节点组成的分布式环境中获取高可靠的锁。它要求在多个(通常是奇数个)独立的Redis节点上尝试获取锁,只有当大多数节点(例如,总共5个节点,至少3个节点)成功获取锁时,才认为锁获取成功。
  • 示例流程(简化)
    • 假设有3个Redis节点node1node2node3,在Python中实现RedLock的基本步骤如下:
      import redis
      import time# 定义Redis节点列表
      redis_nodes = [redis.Redis(host='node1', port=6379),redis.Redis(host='node2', port=6379),redis.Redis(host='node3', port=6379)
      ]lock_key = "my_redlock"
      locked_value = "unique_client_id"
      expire_time = 10
      quorum = len(redis_nodes) // 2 + 1
      acquired_locks = 0# 尝试在多个节点上获取锁
      for node in redis_nodes:try:result = node.set(lock_key, locked_value, ex=expire_time, nx=True)if result:acquired_locks += 1except:pass
      if acquired_locks >= quorum:print("RedLock获取成功")try:# 执行业务逻辑time.sleep(7)finally:# 释放锁,需要向所有节点发送释放请求for node in redis_nodes:try:node.delete(lock_key)except:pass
      else:print("RedLock获取失败")
      
  • 优势与应用场景
    • 提供了更高的可靠性,能够抵抗单个Redis节点故障、网络分区等问题,适用于对数据一致性要求极高的分布式系统,如金融交易系统、分布式任务调度系统等。

4. 基于Lua脚本实现的复杂锁(如可重入锁)

  • 原理
    • Lua脚本在Redis中可以原子地执行多个命令,通过编写Lua脚本可以实现复杂的锁逻辑。例如,实现可重入锁时,可以在脚本中检查锁的持有者是否为当前客户端,如果是,则增加重入次数;如果不是,则判断是否可以获取锁。
  • 示例(简单的可重入锁检查脚本)
    • 以下是一个简单的Redis Lua脚本用于检查可重入锁(假设锁的信息存储在一个哈希表中,键为lock_key,字段owner存储持有者,count存储重入次数):
      -- 检查锁是否存在且持有者是当前客户端
      local lock_key = KEYS[1]
      local client_id = ARGV[1]
      local lock_info = redis.call('hgetall', lock_key)
      if #lock_info == 0 then-- 锁不存在,设置持有者为当前客户端,重入次数为1redis.call('hmset', lock_key, 'owner', client_id, 'count', 1)return 1
      elseif lock_info[2] == client_id then-- 持有者是当前客户端,增加重入次数redis.call('hincrby', lock_key, 'count', 1)return 1
      elsereturn 0
      end
      
    • 在Java中调用这个Lua脚本可以这样实现:
      import redis.clients.jedis.Jedis;
      import redis.clients.jedis.JedisPool;
      import redis.clients.jedis.JedisPoolConfig;
      import redis.clients.jedis.Response;
      import redis.clients.jedis.ScriptingCommands;public class ReentrantRedisLock {private static final String LUA_SCRIPT = "local lock_key = KEYS[1]\n" +"local client_id = ARGV[1]\n" +"local lock_info = redis.call('hgetall', lock_key)\n" +"if #lock_info == 0 then\n" +"    -- 锁不存在,设置持有者为当前客户端,重入次数为1\n" +"    redis.call('hmset', lock_key, 'owner', client_id, 'count', 1)\n" +"    return 1\n" +"elseif lock_info[2] == client_id then\n" +"    -- 持有者是当前客户端,增加重入次数\n" +"    redis.call('hincrby', lock_key, 'count', 1)\n" +"    return 1\n" +"else\n" +"    return 0\n" +"end";private JedisPool jedisPool;public ReentrantRedisLock() {JedisPoolConfig poolConfig = new JedisPoolConfig();jedisPool = new JedisPool(poolConfig, "localhost", 6379);}public boolean tryLock(String lock_key, String client_id) {try (Jedis jedis = jedisPool.getResource()) {ScriptingCommands scriptingCommands = jedis.scriptingCommands();Response<Long> response = scriptingCommands.evalsha(scriptingCommands.scriptLoad(LUA_SCRIPT), 1, lock_key, client_id);return response.get() == 1;}}public void unlock(String lock_key, String client_id) {try (Jedis jedis = jedisPool.getResource()) {// 这里还需要编写释放锁的Lua脚本,此处省略// 基本思路是检查重入次数,减1后如果为0则删除锁的记录}}
      }
      
  • 优势与应用场景
    • 可以实现更灵活、复杂的锁机制,如可重入锁、公平锁等,满足特定业务场景下对锁的高级需求,如在递归调用函数中需要获取同一把锁,或者需要按照请求顺序公平地获取锁的场景。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决edge浏览器无法同步问题

有时候电脑没带&#xff0c;但是浏览器没有同步很烦恼。chrome浏览器的同步很及时在多设备之间能很好使用。但是edge浏览器同步没反应。 在这里插入图片描述 解决方法&#xff1a; 一、进入edge浏览器点击图像会显示未同步。点击“管理个人资料”&#xff0c;进入后点击同步&…

python代码中通过pymobiledevice3访问iOS沙盒目录获取app日志

【背景】 在进行业务操作过程中&#xff0c;即在app上的一些操作&#xff0c;在日志中会有对应的节点&#xff0c;例如&#xff0c;下面是查看设备实时视频过程对应的一些关键节点&#xff1a; 1、TxDeviceAwakeLogicHelper&#xff1a;wakeStart deviceId CxD2BA11000xxxx …

网络编程_day6

目录 【0】复习 并发服务器实现思路梳理 多进程 多线程 IO多路复用select 【1】setsockopt&#xff1a;设置套接字属性 socket属性 设置地址重用 【2】超时检测 必要性 超时检测的设置方法 1. 通过函数自带的参数设置 2. 通过设置套接字属性进行设置 3. alarm函数与sigaction函…

GPT-Sovits-1-数据处理

1.1 切割音频 将音频切割为多个10s内的片段 1.2 降噪 这一步用的是modelscope的pipeline 如果要去除背景音&#xff0c;可以用傅立叶转为为频谱&#xff0c;去除低频部分后再转回来 1.3 提取音频特征 这里用到了 funasr 库 这一步目的是输出音频样本的《文本标签文件》&am…

Linux——常见指令及其权限理解(正在更新中)

1.指令 1.1 快速了解指令 pwd 首次登录&#xff0c;默认所处的路径 whoami 当前所用的用户的名称 ls 显示当前路径下&#xff0c;文件名称 mkdir 在当前目录下&#xff0c;创建一个文件夹/目录 cd 进入一个目录 touch 新建一个文…

Kafka 物理存储机制

优质博文&#xff1a;IT-BLOG-CN 一个商业化消息队列的性能好坏&#xff0c;其文件存储机制设计是衡量一个消息队列服务技术水平和最关键指标之一。下面将从Kafka文件存储机制和物理结构角度&#xff0c;分析Kafka是如何实现高效文件存储&#xff0c;及实际应用效果。Kafka的基…

采用STM32CubeMX和HAL库的定时器应用实例

目录 STM32的通用定时器配置流程 定时器应用的硬件设计 定时器应用的软件设计 1. 通过STM32CubeMX新建工程 通过STM32CubeMX新建工程的步骤如下&#xff1a; 2. 通过Keil MDK实现工程 通过Keil MDK实现工程的步骤如下&#xff1a; STM32的通用定时器配置流程 通用定时器…

【优选算法篇】前缀之序,后缀之章:于数列深处邂逅算法的光与影

文章目录 C 前缀和详解&#xff1a;基础题解与思维分析前言第一章&#xff1a;前缀和基础应用1.1 一维前缀和模板题解法&#xff08;前缀和&#xff09;图解分析C代码实现易错点提示代码解读题目解析总结 1.2 二维前缀和模板题解法&#xff08;二维前缀和&#xff09;图解分析C…

Topaz Video AI for Mac 视频无损放大软件安装教程【保姆级,操作简单轻松上手】

Mac分享吧 文章目录 Topaz Video AI for Mac 视频无损放大软件 安装完成&#xff0c;软件打开效果一、Topaz Video AI 视频无损放大软件 Mac电脑版——v5.3.5⚠️注意事项&#xff1a;1️⃣&#xff1a;下载软件2️⃣&#xff1a;安装软件&#xff0c;将安装包从左侧拖入右侧文…

CNAS软件测试的好处有哪些?上海软件测试中心推荐

在进行软件测试或其他项目检测需要选择软件测试中心时&#xff0c;我们常常会把该公司有无资质认证考虑进去。那么CNAS认可作为检测机构或实验室的一项重要资质认证&#xff0c;我们可能会产生疑问&#xff1a;CNAS认可什么意思?CNAS软件测试又有什么好处呢? 1、CNAS认可是什…

【51 Pandas+Pyecharts | 深圳市共享单车数据分析可视化】

文章目录 &#x1f3f3;️‍&#x1f308; 1. 导入模块&#x1f3f3;️‍&#x1f308; 2. Pandas数据处理2.1 读取数据2.2 查看数据信息2.3 处理起始时间、结束时间2.4 增加骑行时长区间列2.5 增加骑行里程区间列 &#x1f3f3;️‍&#x1f308; 3. Pyecharts数据可视化3.1 各…

AMBA之AXI 总线

AMBA概述 AMBA&#xff08;Advanced Microcontroller Bus Architecture&#xff09;是ARM公司开发的一种高级微控制器总线架构&#xff0c;用于连接处理器、存储器和外设的通信。AMBA总线架构定义了一组协议和接口&#xff0c;用于实现高性能、低功耗、可扩展的系统设计。 AM…

Amcor 如何借助 Liquid UI 实现SAP PM可靠性

背景介绍 安姆科是塑料行业的全球领军企业&#xff0c;该企业认识到 SAP 工厂维护&#xff08;SAP PM&#xff09;对于确保高效的维护管理的重要性。 在诸如制造业等高度依赖机械设备的行业中&#xff0c;SAP PM是一种通过数据驱动决策来最大限度减少停机时间、降低间接成本、…

【C语言】预处理(预编译)详解(下)(C语言最终篇)

文章目录 一、#和##1.#运算符2.##运算符 二、预处理指令#undef三、条件编译1.单分支条件编译2.多分支条件编译3.判断符号是否被定义4.判断符号是否没有被定义 四、头文件的包含1.库头文件的包含2.本地头文件的包含3.嵌套包含头文件的解决方法使用条件编译指令使用预处理指令#pr…

宠物空气净化器哪个牌子好?有没有噪音低的宠物空气净化器推荐?

如今随着社会竞争越来越激烈&#xff0c;不少人开始焦虑内耗&#xff0c;但为了能更好的生活&#xff0c;养宠物便成为不少人的排忧解乏的方法。 我也不例外&#xff0c;作为一名996社畜&#xff0c;天刚亮就出门&#xff0c;天黑很久才回家&#xff0c;所以选择养猫来陪我度过…

C++设计模式创建型模式———生成器模式

文章目录 一、引言二、生成器/建造者模式三、总结 一、引言 上一篇文章我们介绍了工厂模式&#xff0c;工厂模式的主要特点是生成对象。当对象较简单时&#xff0c;可以使用简单工厂模式或工厂模式&#xff1b;而当对象相对复杂时&#xff0c;则可以选择使用抽象工厂模式。 工…

创作三周年:在忙碌中寻找灵感与快乐

目录 机缘 收获 技能的提升 粉丝的积累 正向的反馈 同行的伙伴 日常 运动 旅行 生活 憧憬 结语 机缘 不知不觉已经成为创作者3年了&#xff0c;这一路走来&#xff0c;有过高峰和低谷&#xff0c;但始终让我坚持的&#xff0c;是最初那份简单的初心&#xff1a;我…

C#从零开始学习(用户界面)(unity Lab4)

这是书本中第四个unity Lab 在这次实验中,将学习如何搭建一个开始界面 分数系统 点击球,会增加分数 public void ClickOnBall(){Score;}在OneBallBehaviour类添加下列方法 void OnMouseDown(){GameController controller Camera.main.GetComponent<GameController>();…

分布式搜索引擎elasticsearch操作文档操作介绍

1.DSL查询文档 elasticsearch的查询依然是基于JSON风格的DSL来实现的。 1.1.DSL查询分类 Elasticsearch提供了基于JSON的DSL&#xff08;Domain Specific Language&#xff09;来定义查询。常见的查询类型包括&#xff1a; 查询所有&#xff1a;查询出所有数据&#xff0c;…

软件系统安全保证措施,质量保证措施方案(Word原件套用)

系统安全保证措施是构建稳固防御体系的核心&#xff0c;旨在全方位保障信息系统的安全性。以下是对这七项措施的简要概述&#xff1a; 一、身份鉴别&#xff1a;采用多种认证方式&#xff0c;如密码、生物识别等&#xff0c;确保用户身份的准确无误&#xff0c;防止非法入侵。 …