首页 > 其他分享 >为什么使用分布式锁

为什么使用分布式锁

时间:2024-04-24 22:23:02浏览次数:23  
标签:为什么 Lua 节点 获取 线程 使用 lockKey 分布式

为什么使用分布式锁

为了保证一个方法或属性在高并发情况下的同一时间只能被同一个线程执行

分布式锁应该具备哪些条件?

  • 1.在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行
  • 2.高可用的获取锁和释放锁
  • 3.高性能的获取锁和释放锁
  • 4.具备可重入特性
  • 5.具备锁实效机制,防止死锁
  • 6.具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败

分布式锁的三种实现方式:

分布式的CAP理论告诉我们任何一个分布式系统都无法同时满足「一致性」(Consistency)、「可用性」(Availability)和「分区容错性」(Partition tolerance),最多只能同时满足两项。”所以,很多系统在设计之初就要对这三者做出取舍。在互联网领域的绝大多数的场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。

1.基于数据库实现排他锁

  1. 悲观锁
    利用select … where … for update 排他锁。阻塞的,容易锁表。
  2. 乐观锁
    update version通过增加递增的版本号字段实现乐观锁。

基于redis实现

  • 1.简化版setnx命令
if (jedis.setnx(lockKey, val) == 1) { 
	jedis.expire(lockKey, timeout);
}

很显然,加锁操作和后面的设置超时时间是分开的,并非原子操作。假如加锁成功,但是设置超时时间失败了,该lockKey就变成永不失效。

  • 2.set(lockKey, requestId, "NX", "PX", expireTime)命令,该命令可以指定多个参数。
String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
if ("OK".equals(result)) {
	return true;
}
	return false;
其中:
lockKey:锁的标识
requestId:请求id
NX:只在键不存在时,才对键进行设置操作。
PX:设置键的过期时间为 millisecond 毫秒。
expireTime:过期时间

满足了原子性,但是每次都要达到了超时时间才释放锁,显然也不是很合理,那么如何手工释放锁?

  • 3.finally中释放锁 + 全局唯一标识
try{ String result = jedis.set(lockKey, requestId, "NX", "PX", expireTime);
if ("OK".equals(result)) {
	return true;  
}  
	return false;
} finally {  
	if (jedis.get(lockKey).equals(requestId)) {
		jedis.del(lockKey);    
		return true;     
	}     
	return false; 
	}

无论代码执行成功或失败了,都需要释放锁。如果有异常了,到达超时时间,锁还是会被redis自动释放。
而requestId是全局唯一的,保证了自己只能释放自己加的锁,不存在加锁和释放别人锁的情况。

  • 4.redis+Lua
    Redis+Lua,可以说是专门为解决原子问题而生。Lua专门整合原子操作。有了 Lua 的特性,Redis 才真正在分布式锁、秒杀等场景,有了用武之地。
    为什么要用Lua脚本呢?因为一段复杂的业务逻辑,可以通过封装在Lua脚本中发送给Redis,保证这段复杂业务逻辑执行的原子性。

  • 5.Redision的看门狗
    如果锁达到了超时时间,但业务代码还没执行完怎么办?
    看门狗可以通过定时任务不断刷新锁的获取事件,从而在用户获取锁到释放锁期间保持一直持有锁

eg:我们可以使用TimerTask类,来实现自动续期的功能:获取锁之后,自动开启一个定时任务,每隔10秒钟,自动刷新一次过期时间。这种机制就是redisson框架中的
watch dogTimer timer = new Timer(); 
timer.schedule(new TimerTask() { 
@Override
public void run(Timeout timeout)throws Exception {//自动续期逻辑  } }, 
10000, TimeUnit.MILLISECONDS);

基于zookeeper实现分布式锁

ZooKeeper是一个为分布式应用提供一致性服务的开源组件,它内部是一个分层的文件系统目录树结构,规定同一个目录下只能有一个唯一文件名。基于ZooKeeper实现分布式锁的步骤如下:

  • (1)创建一个目录mylock;
  • (2)线程A想获取锁就在mylock目录下创建临时顺序节点;
  • (3)获取mylock目录下所有的子节点,然后获取比自己小的兄弟节点,如果不存在,则说明当前线程顺序号最小,获得锁;
  • (4)线程B获取所有节点,判断自己不是最小节点,设置监听比自己次小的节点;
  • (5)线程A处理完,删除自己的节点,线程B监听到变更事件,判断自己是不是最小的节点,如果是则获得锁。
    通常使用ZooKeeper的一个客户端Curator,Curator提供的InterProcessMutex是分布式锁的实现,acquire方法用于获取锁,release方法用于释放锁。

总结:

数据库锁

  • db操作性能较差,并且有锁表的风险
  • 非阻塞操作失败后,需要轮询,占用cpu资源;

redis分布式锁:

  • 主从切换的情况下可能出现多客户端获取锁的情况;
  • Lua脚本在单机上具有原子性,主从同步时不具有原子性

基于Zookeeper的分布式锁

  • 需要引入Zookeeper集群,比较重量级;
  • 具备高可用、可重入、阻塞锁特性,可解决失效死锁问题。
  • 因为需要频繁的创建和删除节点,性能上不如Redis方式。

小结
如果你的实际业务场景,更需要的是保证数据一致性。那么请使用CP类型的分布式锁,比如:zookeeper
如果你的实际业务场景,更需要的是保证数据高可用性。那么请使用AP类型的分布式锁,比如:redis;
通常redis足够用了,通过最终一致性大部分即可满足需求了,强一致性实时数据还是要依赖数据库的事务。

标签:为什么,Lua,节点,获取,线程,使用,lockKey,分布式
From: https://www.cnblogs.com/Skyvswfq/p/18156508

相关文章

  • Ollama是什么,为什么这么好用
     Ollama是一个开源框架,专为在本地机器上便捷部署和运行大型语言模型(LLM)而设计。以下是其主要特点和功能概述:1.简化部署:Ollama目标在于简化在Docker容器中部署大型语言模型的过程,使得非专业用户也能方便地管理和运行这些复杂的模型。2.轻量级与可扩展:作为轻量级框架,Olla......
  • debian12安装使用distrobox来启动gui程序
    1.安装distroboxsudoaptinstalldistrobox这里默认使用的容器管理工具是podman,不是docker2.配置podman的注册表以下载镜像在/etc/containers/registries.conf.d/00-unqualified-search-registries.conf添加unqualified-search-registries=["docker.io"]网速不行的话......
  • 使用进程锁和连接池交互
    在多线程环境中,使用连接池和线程锁可以保证数据的安全性和一致性。线程锁(如`threading.Lock()`)用于同步对共享资源的访问,以防止多个线程同时写入数据库时发生冲突。以下是一个使用连接池和线程锁的示例,展示了如何在多线程环境中保证数据的安全性:```pythonimportthreadingfromDB......
  • 使用“数据库提供的事务管理机制来控制并发访问”处理事务
    在数据库中,事务管理机制用于确保一系列操作要么全部完成,要么全部不发生,以保持数据的一致性和完整性。在SQLite中,可以使用`BEGINTRANSACTION`,`COMMIT`,和`ROLLBACK`语句来管理事务。以下是一个使用SQLite的事务管理机制来处理并发访问的示例:```pythonimportthreadingfromD......
  • 多线程、分布式处理事务
    分布式事务涉及到多个独立的数据库系统或者多个独立的事务处理,它们需要在一个全局事务中协调一致。这种事务通常用于分布式系统或者微服务架构中,其中不同的服务可能使用不同的数据库。在Python中,实现分布式事务通常需要依赖特定的分布式事务管理器或者框架。例如,可以使用两阶段......
  • chsime.exe 是 Windows 系统中的一个文件,它是中文输入法编辑器的主要执行文件。这个文
    chsime.exe是Windows系统中的一个文件,它是中文输入法编辑器的主要执行文件。这个文件通常用于启动和管理中文输入法,使用户能够在Windows系统中输入中文字符。通常情况下,当用户需要在Windows系统中输入中文时,他们可以通过点击任务栏上的语言栏或使用快捷键切换到中文输......
  • dcomlaunch 是 Windows 操作系统中的一个服务进程,负责启动和管理分布式组件对象模型(DC
    dcomlaunch是Windows操作系统中的一个服务进程,负责启动和管理分布式组件对象模型(DCOM)应用程序。DCOM是一种微软的远程过程调用(RPC)技术,允许运行在不同计算机上的软件组件相互通信和交互。具体来说,dcomlaunch服务进程的作用包括:启动和管理DCOM服务:dcomlaunch负责启动......
  • 项目管理中,为什么关键路径是完成项目的最短时间?
    关键路径方法(CriticalPathMethod)应用于项目管理中,使用该方法可以计算出完成项目所需的最短时间,在理想情况下,至少需要这么长的时间才能完成该项目。关键路径由一系列关键节点组成,这些节点的有序排列构成了关键路径。每个关键节点都是该项目中的其中一个任务,而每个任务包括任务......
  • DRF之jwt介绍与使用
    一、jwt介绍1、什么是jwtJWT(JSONWebToken)是一种用于在网络应用中传递信息的开放标准(RFC7519)。它通过在用户和服务器之间传递的信息生成具有一定结构的令牌,这些令牌可以袐用于身份验证和信息传递。它是一种前后端登陆认证的方案,区别于之前的cookie,session。2、JWT结构一个J......
  • 项目管理中,为什么关键路径是完成项目的最短时间?
    关键路径方法(CriticalPathMethod)应用于项目管理中,使用该方法可以计算出完成项目所需的最短时间,在理想情况下,至少需要这么长的时间才能完成该项目。关键路径由一系列关键节点组成,这些节点的有序排列构成了关键路径。每个关键节点都是该项目中的其中一个任务,而每个任务包括任务......