实现分布式锁

背景

分布式锁是一种用于协调分布式系统中多个节点之间并发访问共享资源的机制。在分布式系统中,由于存在多个节点同时访问共享资源的可能性,需要使用分布式锁来保证数据的一致性和正确性。

今天要实现的是分布式场景中的互斥类型的锁。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

下面时分布式锁的实现重点
在这里插入图片描述

借助MySQL实现

主要利用MySQL唯一键和唯一性约束来实现互斥性

表结构

DROP TABLE IF EXISTS `dislock`;CREATE TABLE `dislock` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT	COMMENT '主键',`lock_type` varchar(64) NOT NULL COMMENT '锁类型',`owner_id` varchar(255) NOT NULL COMMENT '持锁对象',`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`),UNIQUE KEY `idx_lock_type` (`lock_type`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='分布式锁表';

创建一个名为dislock的表,用于存储分布式锁的信息。该表包含以下字段:

  • id:主键,自增长的整数类型。
  • lock_type:锁类型,字符串类型,用于标识锁的类型。
  • owner_id:持锁对象,字符串类型,用于标识持有锁的客户端或其他相关信息。
  • update_time:更新时间,时间戳类型,表示最后一次更新该行数据的时间。

在上面的SQL语句中,idx_lock_type是一个唯一索引,它定义在lock_type字段上,确保表中不会有两个相同的lock_type值。这样可以保证同一类型的锁在表中只有一条记录,避免了同一客户端重复获取锁的情况。

加锁和解锁

INSERT INTO dislock (`lock_type`, `owner_id`) VALUES ('act_lock', 'ad2daf3');
DELETE FROM dislock WHERE `lock_type` = 'act_lock' AND `owner_id` = 'ad2daf3'; // 要确保谁加锁谁解锁

如果要用MySQL实现的话,**还需要开一个进程(要求计算型高可用),来管理超时,**不断去查询updatetime,如果该锁超过了最长允许存在的时间,则需要删除数据库对应的该行。

如果要实现可重入的话,那么考虑再增加一个数据库字段来实现。

借助Redis实现

在Redis中,可以使用SET命令来实现分布式锁。具体实现方法如下:

  1. 使用SET命令尝试在Redis中设置一个键,例如lock:resource,并将其值设置为一个唯一的标识符,例如当前进程的ID或一个随机字符串。可以使用NX选项来确保只有在该键不存在时才进行设置,从而实现加锁操作。

  2. 如果SET命令返回了OK,则说明该键被成功设置,当前进程获得了锁;否则,说明该键已经被其他进程持有,当前进程没有获得锁,需要等待一段时间后重试。

  3. 在完成操作后,使用DEL命令删除该键,释放锁。

需要注意的是,在使用SET命令设置键的值时,应该设置一个过期时间,以防止锁被持有进程意外终止而无法释放。可以使用EX选项来设置过期时间,例如SET lock:resource <identifier> EX 10表示将锁的过期时间设置为10秒。

另外,为了避免锁的误删除,应该使用与设置键的标识符不同的值来删除锁。可以使用Lua脚本来实现原子性的加锁和解锁操作,从而避免并发问题。例如,下面是一个简单的Lua脚本,实现了基本的加锁和解锁操作:

-- 加锁操作
if redis.call('SET', KEYS[1], ARGV[1], 'EX', ARGV[2], 'NX') thenreturn 1
elsereturn 0
end-- 解锁操作
if redis.call('GET', KEYS[1]) == ARGV[1] thenreturn redis.call('DEL', KEYS[1])
elsereturn 0
end

我们今天主要考虑下面的方法
当使用 Redis 的 Redlock 算法时,需要考虑以下关键步骤和注意事项:

  1. 选择 N 个 Redis 实例

    • 选择的 Redis 实例应该分布在不同的物理服务器或者逻辑节点上,以确保它们不会受到单点故障的影响。
    • 这些实例可以是独立的 Redis 节点,也可以是 Redis 集群中的节点。
  2. 获取当前时间

    • 在进行锁操作之前,首先需要获取一个精确的当前时间戳。这可以通过系统时间或者某种网络时间协议(如NTP)来获得。
  3. 尝试在每个实例上获取锁

    • 对于每个选定的 Redis 实例,使用相同的锁键和唯一的随机值(例如 UUID)执行 SET 操作,并设置适当的超时时间和标识符,以确保只有持有锁的客户端才能释放锁。
    • 设置锁的超时时间是为了避免锁被永久性地持有,即使持有锁的客户端出现故障。
  4. 计算获取锁所需的时间

    • 计算获取锁所需的时间,主要包括获取锁的时间、网络延迟以及时钟漂移等。这些因素都会影响锁的有效性。
  5. 判断是否成功获取锁

    • 如果大多数实例(至少超过半数)成功获取了锁,并且用于获取锁的时间没有超过超时时间,则认为获取锁成功。
    • 如果无法获得大多数实例的支持,可能需要重试或者放弃锁操作。
  6. 释放锁

    • 在完成任务后,需要在所有实例上执行删除操作来释放锁。

注意事项

  • 网络分区:在面对网络分区时,需要考虑如何处理部分 Redis 实例无法通信的情况。这可能需要引入额外的逻辑来检测并处理这种情况。
  • 时钟漂移:由于不同的服务器上的时钟可能存在不同程度的漂移,需要谨慎处理时钟同步问题,以确保锁的超时时间计算准确。
  • Redis 实例故障:需要考虑 Redis 实例的故障处理,包括如何发现故障实例并采取适当的措施。

总之,实现 Redlock 算法需要综合考虑各种因素,并根据具体情况进行调整,以确保系统在分布式环境下能够正确、高效地运行。

代码实现参考:
链接: https://github.com/jacket-code/redlock-cpp

其他的方法未完待续,后续补充

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

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

相关文章

burp靶场--文件上传

burp靶场–文件上传 https://portswigger.net/web-security/file-upload/lab-file-upload-remote-code-execution-via-web-shell-upload 1.文件上传 1、原理&#xff1a;文件上传漏洞是指Web服务器允许用户将文件上传到其文件系统&#xff0c;而不充分验证文件的名称、类型、…

一文详解Bitcoin Wallet(btc钱包),推荐bitget钱包

​ 比特币&#xff08;BTC&#xff09;是什么&#xff1f; 比特币&#xff08;BTC&#xff09;于 2008 年由中本聪创建&#xff0c;是一个去中心化的点对点网络。这个开创性的系统运用了密码学技术和分布式账本技术&#xff0c;无需中央权威机构的验证。比特币的诞生标志着去中…

【Linux的基本指令】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言 1、ls 指令 2、 pwd命令 3、cd 指令 4、touch指令 5、mkdir指令&#xff08;重要&#xff09; 6、rmdir指令 && rm 指令&#xff08;重要&#xff09;…

产品经理NPDP

产品经理是告诉团队做正确的事情&#xff0c;项目经理是告诉团队正确地做事情 产品经理的核心能力是商业洞察能力、产品规划与设计、团队管理能力。 产品经理国际资格认证(NPDP)

Windows系统下使用docker-compose安装mysql8和mysql5.7

windows环境搭建专栏&#x1f517;点击跳转 win系统环境搭建&#xff08;十四&#xff09;——Windows系统下使用docker安装mysql8和mysql5.7 文章目录 win系统环境搭建&#xff08;十四&#xff09;——Windows系统下使用docker安装mysql8和mysql5.7MySQL81.新建文件夹2.创建…

javaWebssh运动会管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh运动会管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,M…

动态规划Day14(子序列第二天)

目录 1143.最长公共子序列 看到题目的第一想法 看到代码随想录之后的想法 自己实现过程中遇到的困难 1035.不相交的线 看到题目的第一想法 看到代码随想录之后的想法 自己实现过程中遇到的困难 53. 最大子序和 看到题目的第一想法 …

Jetson AGX Orin安装archiconda、Pytorch

想在Jetson AGX Orin创建一个虚拟环境&#xff0c;然后安装pytorch&#xff0c;过程中遇到了很多的坑&#xff0c;这篇文章主要用于记录过程~因为Orin本身是Arm架构&#xff0c;X86架构可以装Anaconda&#xff0c;对于ARM要装archiconda。 1.安装archiconda 1.1确定操作系统架…

Spring5深入浅出篇:第一个Spring程序

Spring5深入浅出篇:第一个Spring程序 软件版本 1. JDK1.8 2. Maven3.5 3. IDEA2018 4. SpringFramework 5.1.4官⽅⽹站 www.spring.io环境搭建 Spring依赖 <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency><g…

YOLOv5改进系列(26)——添加RFAConv注意力卷积(感受野注意力卷积运算)

【YOLOv5改进系列】前期回顾: YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析 YOLOv5改进系列(1)——添加SE注意力机制

【Vue】vue项目中Uncaught runtime errors:怎样关闭

vue项目中Uncaught runtime errors:怎样关闭 一、背景描述二、报错原因三、解决方案3.1 只显示错误信息不全屏覆盖3.2 取消全屏覆盖 四、参考资料 一、背景描述 项目本来运行的好好&#xff0c;换了个新的浏览器&#xff0c;新的Chrome浏览器版本号是116.0.5845.97&#xff08…

构建高效外卖系统:技术实践与代码示例

外卖系统在现代社会中扮演着重要的角色&#xff0c;为用户提供了便捷的用餐解决方案。在这篇文章中&#xff0c;我们将探讨构建高效外卖系统的技术实践&#xff0c;同时提供一些基础的代码示例&#xff0c;帮助开发者更好地理解和应用这些技术。 1. 技术栈选择 构建外卖系统…