云栖息地快速启动: 【点击查看更多云产品快速启动】
不知道如何开始。在这里,您可以在几分钟内解决新手入门等基本问题,并且可以快速完成产品配置操作!
分布式锁是大型应用程序中最常见的功能之一。有许多方法可以实现基于Redis的分布式锁。本章首先介绍和分析了分布式锁的常用实现方法,然后根据阿里巴巴集团使用Redis企业版和分布式锁的业务经验,介绍了用Redis企业版实现高性能分布式锁的实用方案。
分布式锁及其应用场景
在应用程序开发中,如果同一进程中的不同线程需要同时访问某个资源,可以使用各种互斥锁和读写锁。如果主机上的多个进程需要同时访问一个资源,那么进程间同步的原语,如信号量、管道、共享内存等。可以使用。但是,如果多个主机需要同时访问一个资源,它们需要使用全局可见且互斥的锁。这种锁是一种分布式锁,它可以在分布式场景中锁定资源,以避免竞争资源导致的逻辑错误。
分布式锁的特性
互斥的
在任何时候,只有一个客户持有锁。
没有死锁
分布式锁本质上是基于租约的租约锁。如果客户端在获取锁后出现异常,则锁可以在一段时间后自动释放,并且资源不会被锁定。
一致性
硬件故障或网络异常等外部问题,以及查询缓慢和自身缺陷等内部因素,都可能导致Redis的高可用性切换,并将副本升级到新的主机。此时,如果业务对互斥有很高的要求,在切换到新的主服务器后,锁需要保持其原始状态。
使用原生Redis实现分布式锁
锁
锁定在中加很简单,只需直接使用SET命令。示例和关键选项描述如下:setresource _ 1 random _ valuenex 5
表1。关键选项的描述
该示例代码将密钥资源_1的到期时间设置为5秒。如果客户端不释放密钥,密钥将在5秒后过期,并且锁将被系统回收。此时,其他客户端将能够再次锁定并访问该资源。
开启
(1)。在时间1),t1,App1设置分布式锁资源_1,过期时间为3秒。
(2).App1由于程序速度慢等原因等待了3秒以上,而resource_1在时间t2被释放。
(3)。在时间3),t3,App2获得这个分布式锁。
释放App2持有的分布式锁。
从上面的过程可以看出,客户端设置的锁必须自己解锁。因此,在使用DEL解锁之前,客户端需要使用GET命令来确认锁是否是自己设置的。在Redis中,通常需要Lua脚本来实现自锁和自我解决:
如果再贴现('get ',KEYS[1])==ARGV[1]那么
返回redis.call('del ',KEYS[1])
其他
返回0
目标
租约续期
当客户端发现操作无法在锁的租用期内完成时,需要延长锁的持有时间并进行更新。像解锁一样,客户端应该只更新它持有的锁。在Redis中,下面的Lua脚本可以用来续订租约。呼叫(' get ',keys [1])==argv [1]然后
返回重发通知( '到期 ',关键[1),阿根廷[2])
其他
返回0
目标
使用Redis企业版实现分布式锁
使用Redis企业性能增强实例的字符串增强命令,可以在没有Lua的情况下实现分布式锁。
锁
锁定方法与本机Redis相同,使用SET命令:setresource _ 1random _ valuenex 5
开启
使用Redis企业版的计算机辅助设计命令:/* if(get(resource _ 1)==my _ random _ value)del(resource _ 1)*/
计算机辅助设计资源_1我的_随机_值
租约续期
可以通过使用CAS命令直接实现租用:CAS资源_ 1 my _ random _ value mey _ random _ value ex 10
基于Jedis的示例代码
定义CAS/CADcommand num tail command implementations protocol command {
计算机辅助设计( '计算机辅助设计 '),计算机辅助设计( '计算机辅助设计 ');
私有最后字节[]raw;
TairCommand(字符串alt) {
raw=安全编码器. encode(alt);
}
@覆盖
公共字节[] getRaw() {
原始返回;
}
}
锁定公共布尔acquired edistributedlock(je dis、stringresource键、strinrandomvalue、intexpiretime)
设定参数设定参数=新设定参数();
setParams.nx()。ex(到期时间);
字符串结果=jedis.set(资源键、随机值、设置参数);
返回“确定”。等于(结果);
}
解锁公共布尔releasestripedlock (jeedis,stringresource键,strinrandomvalue)
jedis.getClient()。发送命令(太命令。计算机辅助设计、资源关键、随机值);
Long ret=jedis.getClient()。getIntegerReply();
ret=ret;
}
公共布尔可更新分布式锁的更新(jedis、stringresource键、strinrandomvalue、intexpiretime)
jedis.getClient()。发送命令(太命令。CAS,资源键,随机值,随机值,'EX ',字符串.值(到期时间));
Long ret=jedis.getClient()。getIntegerReply();
ret=ret;
}
如何保障一致性
Redis的主从同步(复制)是异步的。如果主机在向主机发送修改数据的请求后突然出现异常,并且发生高可用性切换,则缓冲区中的数据可能无法与新主机(原始副本)同步,从而导致数据不一致。如果丢失的数据与分布式锁相关,将会导致锁机制出现问题,从而导致业务异常。以下描述了确保一致性的三种方法。
使用红色锁定
Red lock是由Redis作者提出的一致性解决方案。红色锁的本质是一个概率问题:如果一个主从Reiss在一个高可用性切换期间丢失锁的概率是k%,那么n个独立Reiss同时丢失锁的概率是多少?如果使用红色锁来实现分布式锁,则丢失锁的概率为(1-k%)。鉴于Redis的极高稳定性,此时的概率完全可以满足产品的需求。
红色锁的问题是:
(1)。锁定和解锁的延迟很大。
(2)。很难在集群版本或标准版本(主从架构)的Redis实例中实现。
(3)。它占用了太多的资源。为了实现红锁,有必要创建多个不相关的云Redis实例或自建Redis。
使用WAIT命令。
Redis' WAIT命令会阻止当前客户端,直到该命令之前的所有写命令都成功地从主机同步到指定数量的副本,并且可以在命令中设置以毫秒为单位的等待超时。在云Redis版本中,使用WAIT命令提高分布式锁一致性的一个例子如下:set resource _ 1 random _ value NEX ex5
等待1 5000
使用上述代码,客户端将等待数据成功同步到副本,然后在锁定后继续执行其他操作,最长等待时间为5000毫秒。执行WAIT命令后,如果返回的结果是1,则同步成功,无需担心数据不一致。与红锁相比,这种方法大大降低了成本。
应该指出的是:
(1)。WAIT只会阻止发送它的客户端,不会影响其他客户端。
(2)。WAIT返回正确的值,表明set锁已成功同步到副本。但是,如果在正常返回之前有高可用性交换机,数据可能仍然会丢失。WAIT只能用于表示此时同步可能会失败,并且不能保证数据不会丢失。您可以在WAIT返回异常值后重新锁定或检查数据。
(3)。没有必要使用WAIT来解锁,因为锁只要存在就可以保持互斥,延迟删除不会导致逻辑问题。
不考虑组合方案使用阿里云数据库再版企业版:
(1)。使用红色锁的最大优势在于,Redis节点越多,一致性就越强。
(2)。使用WAIT命令的最大优点是实现成本低。
如果您使用阿里云数据库再版企业版:
(1)。其独特的高可用性高可用性和数据持久性机制可以有效保护数据安全,确保服务的稳定性。它还可以提供高一致性,而无需使用多个Redis节点或WAIT命令。
(2)。用于性能增强实例的CAS/CAD命令可以大大降低分布式锁的开发和管理成本,并提高锁的性能。
(3)。性能增强的实例的多线程性能增强特性使它能够提供本机Redis的三倍性能,并且即使大型并发分布式锁也不会影响正常的Redis服务。
[云起在线教室]产品和技术专家每天分享!
课程地址:https://yqh.aliyun.com/zhibo
立即加入社区,与专家面对面,并了解课程的最新进展!
[云栖在线课堂社区]https://c.tb.cn/F3.Z8gvnK
发表评论