Redis如何实现分布式锁?聊聊实现方法

如何使用 redis 实现分布式锁?下面本篇文章给大家介绍一下基于 redis 实现分布式锁的方法,希望对大家有所帮助!

Redis如何实现分布式锁?聊聊实现方法

在一个分布式系统中,会遇到一些需要对多个节点共享的资源加锁的情况,这个时候需要用到分布式锁。分布式锁通常保存在一个共享的存储系统中,可以被多个节点共享和访问。【相关推荐:Redis视频教程】

锁的本质

简单来讲,锁可以用一个变量来表示。比如,在一个单机多线程的程序来说,某个资源的锁用一个 bit 的数据就可以表示。即 0 表示没有资源可以访问,1 表示资源的锁已被别的线程获取,不能访问。

获取和释放特定资源的锁,本质上就是为获取和修改这个变量的值。如果值是 0 则将其修改为 1,就完成了获取的过程,如果访问到的值不是 0,则获取锁失败;如果之前获取了锁,将表示锁的变量的值修改为 0 的操作,其实就是释放锁的操作。

在一个分布式场景中,实现锁的方式也是一样的,只不过这个表示资源锁的变量,需要保存在一个共享的存储系统中。这个共享的存储系统,可以是 Redis,也可以是其他的任何可以提供数据存储的系统。

基于 Redis 的分布式锁实现

第一步:初步实现功能

对于将 Redis 作为这个共享存储系统的情况来说,代表某个资源的锁的变量,就是 Redis 中的一个键值对。假如,需要添加分布式锁的资源叫 resource_a,我们可以将 Redis 中 resource_a 的锁变量的 key 叫做 lock_a。

例如,节点一需要获取锁,它会访问 Redis 中 lock_a 的值,假设获取到的值为 0,则节点一将这个值设置为 1 后,就完成了加锁操作。此时,节点二也需要获取 resource_a 的锁,它去访问 Redis 中 lock_a 的值,发现值是 1,说明锁已经被别的节点获取,并且还没有释放,因此,节点二对资源 resource_a 加锁失败。

当节点一需要释放锁的时候,只需要将 Redis 中的 lock_a 的值设置为 0 就完成了锁的释放,之后,其他的节点就可以再次获取资源的锁。

第二步:加锁操作原子化

以上的描述中,加锁的并不是一个单一的操作,而是包含了多个步骤:读取锁变量、判断变量的值、修改锁变量。这三个操作需要原子化。

在 Redis 中,有一个 SETNX 命令,用于设置键值对的值,与 SET 命令不同,它在是先事会判断键值对是否存在,只有当指定的 KEY 不存在的时候,才会执行值的设定,否则什么都不执行。SETNX 就是「SET if Not eXist」的意思。它的用法与 SET 相同:

SETNX lock_a 1

登录后复制

这样,当需要获取锁的时候,使用 SETNX 命令为 lock_a 设置一个值,如果设置成功则获取到了锁,如果失败则没有获取到锁;当需要释放锁的时候,使用 DEL 操作删除键值对即可。

这样就实现了获取和释放锁的原子化操作。

第三步:防止加锁后不释放

接下来早考虑一个问题,如果节点一获取到锁之后,由于程序异常等原因,导致一直么有释放锁,此时,锁会一直被它持有,无法释放,其他节点也无法访问资源。

为了避免这种情况的发生,我们必须给锁变量设置过期时间,当锁变量过期后,就可以重新请求加锁,这样就可以避免这个问题。

SETNX 的命令并没有设置过期时间的选项,所幸的是,Redis 为 SET 命令提供了模拟 SETNX 的 NX 选项,我们可以这样设置过期时间:

SET lock_a 1 NX PX 10000

登录后复制

以上命令代表,如果 lock_a 不存在,则将它的值设置为 1,并且在 10 秒后过期。

第四步:谁加锁谁释放

最后一个问题是,如果节点一获取了锁,而由于某种原因,节点二执行了 DEL 操作,那么,其他节点又可以获取锁了。

为了解决这个问题,我们可以修改一下锁变量保存的内容。在前面的逻辑中,我们申请锁的时候,是去判断锁变量是否存在,而与其中保存的值关系不大,因此,我们可以把这个值利用起来。

在加锁的时候,如果把值保存为每个节点唯一的标识,那么,在释放锁执行 DEL 之前再对这个值进行判断,那么,就可以先判断锁是否是当前节点加上的,是的话再进行释放,这样就实现了「谁加锁谁是放」。

这一部分,没有一个单一的指令可以完成读取锁变量、判断、删除的操作,因此,可以使用 Lua 脚本实现。在脚本中获取到当前锁变量的值,与给定的节点标识进行比对,符合的话才进行删除操作,否则不操作。

在释放锁时,执行 Lua 脚本即可。

第五步:实现高可用

完善了功能之后,最后再来实现高可用。如果我们使用单一的 Redis 作为分布式锁的共享存储系统,那么,如果这个 Redis 不可用了,那涉及到分布式锁的部分都不可用了,这样是很脆锁的,这是高可用非常有必要的原因。

此时,需要搬出 Redis 的作者 Antirez 提出的分布式锁算法 Redlock。简而言之,是让锁的申请者,想多个独立的 Redis 实例请求加锁,如果能在半数以上的 Redis 完成枷锁操作,那么就成功的获取了锁,反之获取失败。

在释放锁的操作时,同样只要在超过半数的实例上执行成功删除锁变量的 Lua 脚本,即可视为成功。

更多编程相关知识,请访问:编程入门!!

以上就是Redis如何实现分布式锁?聊聊实现方法的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2039702.html

(0)
上一篇 2025年2月24日 00:04:07
下一篇 2025年2月18日 04:58:50

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 深入聊聊Redis中的双链表

    本篇文章带大家了解一下redis 数据结构中的双链表,简单介绍一下双链表的运用,希望对大家有所帮助! 在 Redis 数据类型中的列表list,对数据的添加和删除常用的命令有 lpush,rpush,lpop,rpop,其中 l 表示在左侧…

    2025年2月24日
    200
  • 深入浅析Redis中的位图(bitmap)

    本篇文章带大家了解一下redis中的位图(bitmap),希望对大家有所帮助! Redis 的位图(bitmap)是由多个二进制位组成的数组,数组中的每个二进制位都有与之对应的偏移量(从 0 开始),通过这些偏移量可以对位图中指定的一个或多…

    2025年2月24日
    200
  • 分享一些好用Redis可视化工具

    本篇文章给大家总结了几款好用redis可视化工具,觉得挺不错的,现在分享给大家,也给大家做个参考,希望对大家有所帮助! 不啰嗦,我们直接开始! 1、命令行 1.1、iredis 利用iredis,用|将redis通过pipe用shell的其…

    2025年2月24日 数据库
    200
  • 整理一些常见Redis数据结构(总结)

    本篇文章给大家整理分享一些常见redis数据结构,还有一些常用指令整理,希望对大家有所帮助! 什么是数据结构? 有Java基础的应该知道常用的一些数据结构,比如数组、队列、栈等等… 那Redis的数据结构跟Java的数据结构有什…

    2025年2月24日
    200
  • 分享一些好用的Redis运维工具

    本篇文章给大家分享一些好用的redis运维工具,看看怎么进行运行状态监控、数据迁移、集群管理,希望对大家有所帮助! 我们在应用Redis时,经常会面临的运维工作,包括Redis的运行状态监控,数据迁移,主从集群、切片集群的部署和运维。接下来…

    2025年2月24日
    200
  • 聊聊Redis数据结构中的String类型

    本篇文章带大家一起了解一下redis数据结构中的string类型,并聊聊redis的kv存储结构,希望对大家有所帮助! Redis常用作分布式KV缓存,很多人仅仅只会使用,却不知道底层却有着很多不为人知的秘密。【相关推荐:Redis视频教程…

    2025年2月24日
    200
  • Redis学习之聊聊单线程的reactor模型

    本篇文章带大家聊聊redis中单线程的reactor模型,i/o模型,还有多线程版本i/o模型,希望对大家有所帮助! redis 的高性能 纯内存访问,所有数据都在内存中,所有的运算都是内存级别的运算,内存响应时间的时间为纳秒级别。因此 r…

    2025年2月24日
    200
  • 浅谈Redis中消息队列和延时消息队列的实现方法

    redis如何实现消息队列与延时消息队列?下面本篇文章给大家介绍一下redis中消息队列和延时消息队列的实现方法,希望对大家有所帮助! 提到redis,更多的可能想到用作缓存的用途,其实redis也可以实现一些简单的消息队列用途,我们可以使…

    2025年2月24日 数据库
    200
  • 实战:通过示例代码聊聊Redis中的list命令

    本篇文章给大家介绍一下redis中的list命令,通过代码示例了解一下list命令的用法,希望对大家有所帮助! list的数据结构 List类型是一个双端链表的结构,容量是2的32次方减1个元素,即40多亿个;其主要功能有push、pop、…

    2025年2月24日
    200
  • 聊聊Redis中的Sentinel机制,介绍一下用法!

    本篇文章带大家了解一下redis中的sentinel机制,介绍一下运行sentinel有两种方式,希望对大家有所帮助! 1. 概述 Redis-Sentinel是Redis官方推荐的高可用性(HA)解决方案,当用Redis做Master-s…

    2025年2月24日
    200

发表回复

登录后才能评论