专栏首页服务端思维Redis分布式锁背后的原理

Redis分布式锁背后的原理

什么是分布式锁?

分布式锁是控制分布式系统或不同系统之间共同访问共享资源的一种锁实现,如果不同的系统或同一个系统的不同主机之间共享了某个资源时,往往需要互斥来防止彼此干扰来保证一致性。

分布式锁需要具备哪些条件?

  • 互斥性:在任意一个时刻,只有一个客户端持有锁。
  • 无死锁:即便持有锁的客户端崩溃或者其他意外事件,锁仍然可以被获取。
  • 容错:只要大部分Redis节点都活着,客户端就可以获取和释放锁。

场景

以前大学照着网上的项目视频做商城的时候,用到Redis。不过基本上都是用来当缓存,但是实际上的应用远不止缓存,所以今天分享一个分布式锁的场景和应用。

在逛商城的时候进行购物支付,基本都是分布式系统,那么用户支付的时候就要上锁,保证不能多线程操作,Redis分布式锁就差不多是这么一个位置:

从业务的角度考虑是非常合理的,它保证了查询及插入数据整个流程的原子性,防止查到脏数据,使得支付流程是一个串行化操作。

接下来就来讲一个Redis分布式锁的一个知识点。

为什么要使用分布式锁?

在实际项目中见过分布式锁后,就不难理解为什么要用分布式锁了。总的来说就是分布式系统要访问共享资源,为了避免并发访问资源带来的错误,我们为共享资源添加一把锁,让各个访问互斥,保证并发访问的安全性,这就是使用分布式锁的原因。

Redis中分布式锁的实现

命令格式:

SETNX key value

将key的值设为value,当且仅当key不存在。若给定的key已经存在,则SETNX不做任何动作。SETNX是SET if Not eXists的简写。

返回值:

返回整数,具体为

  • 1,当key的值被设置
  • 0,当key的值没被设置

Redis中使用分布式锁很简单,只要使用setnx指令对某个key上锁就行:

setnx lock test //上锁
del lock test //解锁

当然我们还可以在上锁之后使用expire指令给锁设置过期时间。

假如我们的程序不使用指令解锁,靠redis设置时间过期来解锁,貌似会出问题。假如我们的服务进程在执行setnx之后和执行expire指令之前挂掉了,那么这个锁岂不是永远都不会被释放?

没错,这确实是个问题,当时人们在Redis的开源社区提出一堆解决方案专门来解决这个问题,可实现方式都极为复杂。后来Redis的作者在Redis2.8版本中假如了set指令的扩展参数,使得setnx指令和expire指令能够同时执行,具体使用像下面一样:

set lock test ex 5 nx
ex:设置键的过期时间
nx:只在键不存在的时候,才对键进行设置操作

从此以后,Redis成为了分布式锁的宠儿。

集群Redis的分布式锁

在Redis的分布式环境中,Redis 的作者提供了RedLock 的算法来实现一个分布式锁。

加锁

  • 获取当前Unix时间,以毫秒为单位。
  • 依次尝试从N个实例,使用相同的key和随机值获取锁。在步骤2,当向Redis设置锁时,客户端应该设置一个网络连接和响应超时时间,这个超时时间应该小于锁的失效时间。例如你的锁自动失效时间为10秒,则超时时间应该在5-50毫秒之间。这样可以避免服务器端Redis已经挂掉的情况下,客户端还在死死地等待响应结果。如果服务器端没有在规定时间内响应,客户端应该尽快尝试另外一个Redis实例。
  • 客户端使用当前时间减去开始获取锁时间(步骤1记录的时间)就得到获取锁使用的时间。当且仅当从大多数(这里是3个节点)的Redis节点都取到锁,并且使用的时间小于锁失效时间时,锁才算获取成功。
  • 如果取到了锁,key的真正有效时间等于有效时间减去获取锁所使用的时间(步骤3计算的结果)。
  • 如果因为某些原因,获取锁失败(没有在至少N/2+1个Redis实例取到锁或者取锁时间已经超过了有效时间),客户端应该在所有的Redis实例上进行解锁(即便某些Redis实例根本就没有加锁成功)。

解锁

向所有的Redis实例发送释放锁命令即可,不用关心之前有没有从Redis实例成功获取到锁.

总结

这次对Redis分布式锁的探索算是加深了自己对Redis的理解,但是Redis的用处远远不止缓存和分布式锁,后面慢慢摸索吧。

本文分享自微信公众号 - 服务端思维(gh_c3775931ac9d)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-10-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • MySQL单表数据不要超过500万行:是经验数值,还是黄金铁律?

    今天,探讨一个有趣的话题:MySQL 单表数据达到多少时才需要考虑分库分表?有人说 2000 万行,也有人说 500 万行。那么,你觉得这个数值多少才合适呢?

    用户2781897
  • 九种高性能可用高并发的技术架构总结,你了解几种?

    分层架构是逻辑上的,在物理部署上,三层架构可以部署在同一个物理机器上,但是随着网站业务的发展,必然需要对已经分层的模块分离部署,即三层结构分别部署在不同的服务器...

    用户2781897
  • Tomcat进程意外退出,元凶居然是他...

    节前某个部门的测试环境反馈tomcat会意外退出,我们到实际环境排查后发现不是jvm crash,日志里有进程销毁的记录,从pause到destory的整个过程...

    用户2781897
  • 由Redis的hGetAll函数所引发的一次服务宕机事件

    昨晚通宵生产压测,终于算是将生产服务宕机的原因定位到了,心累。这篇文章,算作一个复盘和记录吧。。。先来看看Redis的缓存淘汰算法思维导图:

    写博客的老张
  • 那些年用过的Redis集群架构(含面试解析)

    他面试的时候,身份是某知名公司的小码农一枚,却因为不懂自己生产上Redis是如何部署的,导致面试失败!

    Java团长
  • redis配置文件相关

    1. 默认情况下,redis不是在后台运行的,如果需要在后台运行,把该项的值更改为yes daemonize no 2. 当Redis在后台运行时,Redis...

    joshua317
  • Redis 的 8 大应用场景!

    之前讲过Redis的介绍,及使用Redis带来的优势,这章整理了一下Redis的应用场景,也是非常重要的,学不学得好,能正常落地是关键。

    Java技术栈
  • Redis应用场景

    Redis开创了一种新的数据存储思路,使用Redis,我们不用在面对功能单调的数据库时,把精力放在如何把大象放进冰箱这样的问题上,而是利用Redis灵活多变的数...

    张善友
  • 对话张冬洪 | 全面解读NoSQL数据库Redis的核心技术与应用实践

    互联网和Web的蓬勃发展正在改变着我们的世界,随着互联网的不断发展和壮大,企业数据规模越来越大,并发量越来越高,关系数据库无法应对新的负载压力,随着Hadoop...

    数据和云
  • 大厂和初创公司都在用!Redis好在哪?终于有人讲明白了

    Redis从一个不为人熟知、只有少量应用的崭新数据库,逐渐变成了内存数据库领域的事实标准。时至今日,经过大量的实践应用,Redis简洁高效、安全稳定的特性已经深...

    华章科技

扫码关注云+社区

领取腾讯云代金券