当前位置: 首页 > 科技观察

还不知道Redis分布式锁背后的原理?还不赶紧去了解

时间:2023-03-19 15:31:03 科技观察

以前在学校做小项目的时候用过Redis,基本只是用来做缓存的。但是阿芬在工作中发现,Redis在生产中不仅仅只是作为缓存使用。在阿芬接触的项目中,Redis起到了分布式锁的作用。具体情况如下:该项目负责某金融平台的某项业务。它是一个分布式系统,在线运行的大约有10个。左和右的例子。其中一个步骤需要用户支付一定的费用,而Redis分布式锁大概处于这样一个位置:可以看到分布式锁安装完成后,系统做了两次查询检查,然后插入一个订单到数据库记录,然后解锁,进入支付流程。从业务角度理解分布式锁很容易。保证整个查询和插入数据过程的原子性,防止查询校验时发现脏数据,支付前序列化订单信息操作。.虽然从业务角度很容易理解,但是使用Redis作为分布式锁对我来说是一个新知识。阿芬打算结合项目中的代码,深入挖掘这个知识点。正文1.为什么要使用分布式锁在实际项目中看到分布式锁后,就不难理解为什么要使用分布式锁了:综上所述,分布式系统需要访问共享资源,以避免并发访问资源。出错了,我们在共享资源上加一把锁,让每次访问互斥,保证并发访问的安全。这就是使用分布式锁的原因。2、Redis中分布式锁的实现在redis中使用分布式锁非常简单,只需要使用setnx命令锁定一个key即可:setnxlocktest//lockdellocktest//当一个key没有被占用时unlock,setnx指令会返回1,否则返回0,这就是Redis中使用分布式锁的原理。当然我们也可以使用expire命令为锁上锁后设置过期时间。看到这里,你可能会有疑惑。如果我们的程序流程不使用指令解锁,而是依赖redis来设置过期时间,貌似会有问题。如果我们的服务进程在执行setnx之后,执行expire命令之前就挂了,那锁不就永远释放不了吗?是的,这确实是一个问题。当时,人们在Redis的开源社区提出了一堆解决方案,专门解决这个问题,实现方法极其复杂。后来Redis的作者在Redis2.8版本中加入了set命令的扩展参数,使得setnx命令和expire命令可以同时执行。具体使用如下:setlocktestex5nxex:设置key的过期时间nx:只有当key不存在时,才设置key。从此,Redis成为了分布式锁的宠儿。三、分布式锁在Redis集群中遇到的麻烦在学习了Redis中分布式锁的使用之后,我们很快又发现了新的问题。在企业中,Redis基本都是集群部署的,集群部署无法避免一个节点宕机的问题。我们考虑这样一种情况:假设我们在redis的master节点上加了一个分布式锁。不幸的是,主节点挂了,主节点上的锁还没有同步到从节点上。如果有客户端请求获取相同的锁,就会成功获取锁,而之前的锁会被无情的忽略掉。这就是分布式锁在Redis集群中遇到的麻烦。为了解决这个问题,Redis的作者提出了一种叫做Redlock的算法。它的原理是:加锁时,向一半以上的节点发送set命令。只要成功设置了一半以上的锁,就认为本次加锁成功;解锁时,会向所有节点发送del命令。从这个算法的原理可以看出,由于Redlock需要同时对多个节点进行读写,所以使用Redlock加分布式锁的性能要比单机Redis低很多。因为主从复制出错的概率极低,如果你对分布式锁过程有一定的容错率,可以考虑直接使用set命令;如果追求高可用,可以考虑使用Redlock算法。当然,高可用的分布式锁并不局限于Redis的Redlock,我们还可以使用zookeeper或者支持事务的数据库作为分布式锁。?zookeeper的分布式锁原理简单介绍:假设zk使用某个节点作为分布式锁,当不同的客户端来zk争夺这个锁时,zk会依次为不同的客户端创建一个子节点,挂在该节点下as分布式锁。假设第一个来的客户端是A,第二个客户端是B,第一个连接到分布式节点的节点是A,B跟随A,B会监控A的生命状态,当A释放锁时,A将被删除。这时B会监听到A被删除了,B就可以拿到宿主机的分布式锁了。?在公司的项目中,虽然Redis是以集群的形式部署的,但是还是使用了最基本的set命令来获取分布式锁,因为这种方式的性能比Redlock算法要高很多,也比zk、数据库等的分布式锁实现。虽然在高性能和低概率错误之间选择了高性能,但是项目中已经做了其他工作来覆盖错误情况,比如公司项目中主从复制时错误情况会抛出异常,然后一些将根据异常执行重试操作。综上所述,这次对Redis分布式锁的探索加深了我对Redis的理解,但是我知道Redis远比分布式锁和缓存好用,保存下来继续探索。