分布式(三)——实现分布式锁

分布式锁是在多节点环境中确保资源互斥访问的一种机制。它需要满足高可用性、高性能、可重入性、锁失效机制和非阻塞特性。常见的实现方式包括基于数据库、Redis和Zookeeper。数据库实现通过操作表记录实现锁,但可能面临锁的持久化和性能问题。Redis实现利用其高性能和命令支持,通过setnx和expire命令加锁和设置超时,以保证锁的自动释放。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在单机应用中,对一个共享变量进行多线程同步访问的时候,可以是用JVM的synchronized锁或lock锁处理。
但当在分布式集群系统中,多线程、多进程分布在不同机器上,这将使原单机部署情况下的并发控制锁策略失效。
在这里插入图片描述
所以提出一种可以跨机器互斥机制来控制共享资源的访问——分布式锁

一、分布式具备的条件

  1. 在分布上系统环境下,一个方法在同一时间只能被一个机器上的一个线程访问
  2. 高可用的获取锁和释放锁
  3. 高效的获取锁和释放锁
  4. 具备可重入特性(重新进入,由多个任务并发使用,不比担心数据错误)
  5. 具备锁的失效机制,防止死锁
  6. 具备非阻塞锁的特性,没有获取到锁,直接返回获取锁失败

二、三种实现方式

分布式系统要遵守CAP理论:

C(Consistency):一致性
A(Availability):可用性
P(Partition Tolerance):分区容错性

这三者不能同时实现,在绝大多数场景中,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”。

实现分布式锁的三种实现方式主要是:

  • 基于数据库实现分布式锁
  • 基于redis实现分布式锁
  • 基于Zookeeper实现分布式锁

基于笔者目前未了解过Zookeeper,所以暂时不将基于Zookeeper实现分布式锁,等后面学习了再说~

三、基于数据库实现分布式锁

创建一张锁表,通过操作该表的数据来实现。

DROP TABLE IF EXISTS `methodLock`;
CREATE TABLE `methodLock` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
  `method_name` varchar(64) NOT NULL COMMENT '锁定的方法名',
  `desc` varchar(255) NOT NULL COMMENT '备注信息',
  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uidx_method_name` (`method_name`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='锁定中的方法';

method_name做了唯一性约束
当需要锁定某个方法或资源时,在锁表中插入记录,如果有多个请求同时提交到数据库的话,数据库会保证只有一个操作可以成功

INSERT INTO methodLock (method_name, desc) VALUES ('methodName', '锁定的方法名或资源名');

释放锁的时候删除记录

DELETE FROM methodLock WHERE method_name='methodName';

使用数据库实现分布式锁虽然简单,但有些问题还需要解决:

  1. 分布式锁的可用性及性能直接受数据库的可用性及性能影响;
  2. 没有锁失效的机制,当因为服务器宕机导致释放锁的时候没有删除数据,这样后面服务器恢复后一直获取不到锁。所以需要有字段记录失效时间,通过定时任务删除失效的数据;
  3. 不具备阻塞锁特性,获取不到锁直接返回失败,所以需要优化获取逻辑,循环多次去获取
  4. 不具备可重入的特性,当一台机器获到锁后,无法再次成功插入数据。所以需要有字段记录机器线程信息,获取锁时与当前获取到的机器和现场信息,如果相同,则直接获取锁。

四、基于Redis实现分布式锁

redis有很高的性能
redis命令对此支持较好,使用起来也方便。

4.1 实现思想

  • 获取锁的时候,通过setnx加锁,锁的value值为一个随机生成的UUID,通过此在释放锁的时候进行判断
  • 获取锁的时候,用expire命令为锁添加一个超时时间,超过这个时间则放弃获取锁
  • 释放锁的时候,通过UUID判断是不是该锁,若是该锁,则执行delete进行锁释放

4.2 使用命令

  • setnx:命令在指定的 key 不存在时,为 key 设置指定的值,设置成功,返回 1 。 设置失败,返回 0
  • expire:设置 key 的过期时间,key 过期后将不再可用。单位以秒计
  • delete:删除key值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值