茂名seo站内优化,海外全网推广,十大资本投资公司,如何做自助搜券网站分布式锁是一种用于在分布式系统中控制对共享资源的访问的锁。它与传统的单机锁不同#xff0c;因为它需要在多个节点之间协调以确保互斥访问。
本文将介绍什么是分布式锁#xff0c;以及使用Redis实现分布式锁的几种方案。 一、前言
了解分布式锁之前#xff0c;需要先了…分布式锁是一种用于在分布式系统中控制对共享资源的访问的锁。它与传统的单机锁不同因为它需要在多个节点之间协调以确保互斥访问。
本文将介绍什么是分布式锁以及使用Redis实现分布式锁的几种方案。 一、前言
了解分布式锁之前需要先了解一下
线程锁进程锁CAP理论
线程锁
线程锁主要用来给方法、代码块加锁。
当某个方法或代码使用锁在同一时刻仅有一个线程执行该方法或该代码段。
线程锁只在同一JVM中有效果因为线程锁的实现是通过线程之间共享内存实现的
一般实现方法
SynchronizedLock
进程锁
进程锁是控制同一操作系统中多个进程访问某个共享资源
进程具有独立性各个进程无法访问其他进程的资源因此无法通过synchronized等线程锁实现进程锁。
CAP理论
任何一个分布式系统都无法同时满足
一致性Consistency可用性Availability分区容错性Partition tolerance
最多只能同时满足两项。
二、分布式锁
概念
如果不同的系统或同一个系统的不同主机之间共享了某个临界资源往往需要互斥来防止彼此干扰以保证一致性就产生了分布式锁。包含三个要素
分布式系统不同进程共同访问共享资源
分布式锁实现的是CA即一致性和可用性
特性
互斥性: 任意时刻只有一个客户端能持有锁。锁超时释放持有锁超时可以释放防止不必要的资源浪费也可以防止死锁。可重入性:一个线程如果获取了锁之后,可以再次对其请求加锁。高性能和高可用加锁和解锁需要开销尽可能低同时也要保证高可用避免分布式锁失效。安全性锁只能被持有的客户端删除不能被其他客户端删除。
三、实现方案
Redisson框架
框架介绍
Redisson是一款基于Java的Redis客户端它封装了Redis的Java客户端Jedis、Lettuce等并且提供了许多额外的功能例如分布式锁、分布式集合、分布式对象、布隆过滤器等。
框架特点
提供了丰富的API简单易用。提供了多种数据结构的实现如分布式锁、分布式集合、分布式Map、分布式Queue等。支持多种Redis部署方式如单节点、主从、哨兵、集群等。提供了基于Netty的高性能的Redis连接池。提供了基于Ramp模型的分布式远程调用框架可以方便的进行分布式服务调用。
简单示例
1.引入Redisson的依赖
dependencygroupIdorg.redisson/groupIdartifactIdredisson/artifactIdversion3.16.0/version
/dependency
2.创建RedissonClient对象
Config config new Config();
config.useSingleServer().setAddress(redis://127.0.0.1:6379);
RedissonClient redissonClient Redisson.create(config);
3.使用RedissonClient对象进行数据操作
// 获取字符串对象
RBucketString bucket redissonClient.getBucket(myKey);
bucket.set(myValue);// 获取Map对象
RMapString, String map redissonClient.getMap(myMap);
map.put(key1, value1);// 获取分布式锁对象
RLock lock redissonClient.getLock(myLock);
lock.lock();
try {// do something
} finally {lock.unlock();
}
基于SETNX命令实现
通过使用Redis中的SETNX命令即SET if Not eXists可以实现一个简单的分布式锁。
SETNX命令是Redis中的一种原子性操作用于将一个键值对key-value设置到Redis中仅在键不存在时才会设置成功否则设置失败。利用SETNX命令的特性可以实现分布式锁的机制具体步骤如下
设置锁在Redis中设置一个键值对键为锁名称值为一个随机生成的字符串同时设置过期时间防止锁一直存在导致死锁。可以使用以下Redis命令
SETNX lock_name random_value
EXPIRE lock_name expire_time
获取锁如果SETNX命令返回1则说明锁设置成功此时获取到了锁如果返回0则说明锁已经被其他节点持有此时需要等待一段时间后重试获取锁。释放锁释放锁时需要先判断当前线程持有的锁是否与之前设置的锁名称和值相同如果相同则通过DEL命令删除该键值对释放锁。
if redis.call(get, KEYS[1]) ARGV[1] thenreturn redis.call(del, KEYS[1])
elsereturn 0
end
基于RedLock实现
RedLock是一个多节点分布式锁算法它基于Redis和一些简单的算法来实现高可用的分布式锁。
与传统的Redis分布式锁方案相比RedLock可以更好地应对网络故障和硬件故障等异常情况提高系统的可用性和稳定性。
RedLock算法的基本思想是将锁的持有和释放过程转化为一个竞争资源的问题通过多节点协作的方式来实现锁的分配和释放。
具体步骤如下
对于要加锁的资源计算出一个唯一的标识比如使用hash函数将资源名称转化为一个32位整数作为锁的名称。获取多个Redis节点的当前时间戳并计算出一个时钟偏差clock drift。时钟偏差可以通过取多个Redis节点的时间戳的平均值来计算。这样可以避免不同Redis节点之间的时间不同步而导致的锁冲突问题。获取锁对于每个Redis节点尝试通过SET命令获取锁。如果获取锁成功则记录锁的名称、锁的值一个随机字符串、过期时间以及Redis节点的标识信息比如IP地址和端口号。如果获取锁失败则记录失败的节点信息。判断获取锁的结果统计获取锁成功的节点数并根据Quorum算法投票算法来判断是否获取锁成功。如果获取锁成功的节点数大于等于N/21其中N为Redis节点数则表示锁获取成功否则表示锁获取失败。执行结果如果锁获取成功则执行相应的业务逻辑如果锁获取失败则需要尝试在所有失败的节点中找到一个最新的锁并释放它以避免死锁问题。释放锁释放锁时需要根据锁的名称和值来判断当前节点是否持有该锁。如果当前节点持有该锁则通过DEL命令删除该键值对释放锁。
需要注意的是RedLock算法并不能保证绝对的可用性和正确性仍然可能存在某些特殊情况下的锁冲突问题。
因此在实际应用中需要根据具体业务场景和需求来选择适合的分布式锁方案并进行充分的测试和优化。
基于Lua脚本实现
在Redis中可以使用Lua脚本来实现分布式锁其基本思想是通过原子操作将锁的获取和释放过程合并为一个操作保证锁的原子性和一致性。
使用Lua脚本可以在Redis中实现一个基于SET命令的分布式锁具体实现步骤如下
生成一个随机字符串作为锁的值以确保不同的客户端使用的锁值不同。使用SET命令将锁名作为key锁值作为value过期时间作为expire参数来设置锁加上NXNot eXist选项只有当key不存在时才设置成功。在Lua脚本中使用eval命令执行以下脚本
if redis.call(set, KEYS[1], ARGV[1], NX, PX, ARGV[2]) thenreturn 1
elsereturn 0
end
其中KEYS[1]表示锁的名称ARGV[1]表示锁的值ARGV[2]表示锁的过期时间。
结果如果eval命令返回1则表示获取锁成功如果返回0则表示获取锁失败。释放锁时可以使用DEL命令删除锁的名称即可。
下面是一个完整的Lua例子
if redis.call(setnx, KEYS[1], ARGV[1]) 1 thenredis.call(expire, KEYS[1], ARGV[2])return 1
elsereturn 0
end-- 释放锁
if redis.call(get, KEYS[1]) ARGV[1] thenreturn redis.call(del, KEYS[1])
elsereturn 0
end
上面的代码包括两个部分获取锁和释放锁。
获取锁使用setnx命令来尝试获取锁。如果获取成功则设置锁的过期时间并返回1表示获取锁成功否则返回0表示获取锁失败。释放锁先通过get命令获取锁的值判断当前节点是否持有该锁。如果持有则使用del命令删除该键值对并返回1表示释放锁成功否则返回0表示释放锁失败。
四、总结
上面提到的通过Redis实现的分布式锁几种方案在高并发的情况下可能存在锁冲突的问题因此需要根据实际业务场景来选择适合的锁方案并进行充分的测试和优化。
最后推荐一款应用开发神器
扯个嗓子关于目前低代码在技术领域很活跃
低代码是什么一组数字技术工具平台能基于图形化拖拽、参数化配置等更为高效的方式实现快速构建、数据编排、连接生态、中台服务等。通过少量代码或不用代码实现数字化转型中的场景应用创新。它能缓解甚至解决庞大的市场需求与传统的开发生产力引发的供需关系矛盾问题是数字化转型过程中降本增效趋势下的产物。
这边介绍一款好用的低代码平台——JNPF快速开发平台。近年在市场表现和产品竞争力方面表现较为突出采用的是最新主流前后分离框架SpringBootMybatis-plusAnt-DesignVue3。代码生成器依赖性低灵活的扩展能力可灵活实现二次开发。
以JNPF为代表的企业级低代码平台为了支撑更高技术要求的应用开发从数据库建模、Web API构建到页面设计与传统软件开发几乎没有差异只是通过低代码可视化模式减少了构建“增删改查”功能的重复劳动还没有了解过低代码的伙伴可以尝试了解一下。
应用https://www.jnpfsoft.com/?csdn
有了它开发人员在开发过程中就可以轻松上手充分利用传统开发模式下积累的经验。所以低代码平台对于程序员来说有着很大帮助。