ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

面试必问:redis分布式锁

2021-06-21 21:58:29  阅读:176  来源: 互联网

标签:释放 必问 请求 过期 redis 问题 分布式


众所周知,redis是一个开源的高性能的基于内存运行的键值对数据库,现在众多商品信息网站和app在应用着redis,那么redis的安全性能也就值得注意,本文基于redis如何实现分布式锁和锁的一些问题进行讨论,都是个人总结的,借鉴自敖丙大佬,若有偏差,还请多多批评!

既然是分布式锁,萌新肯定会疑问,为什么会有分布式锁,这里就先大概说一下分布式锁是怎么来的。

框架的演进:
传统互联网最开始的架构为单体架构,即前端和后端都在一个web项目中,部署到一台tomcat容器上,各部分之间紧密解耦,不宜开发和扩展。
单体

这时我们将单体架构内部应用拆开,具体的按照分类打包项目,垂直拓展成多个模块,分属不同项目,解决了并发,但是就会出现很多重复代码,且相互之间无法调用,这就为分布式的发展提供了动力。
垂直
在一个分布式的系统中我们将整个服务拆分成服务层和表现层,服务层提供服务,表现层控制页面交互,解决了代码重复,但是又出现了多层调用的关系。
分布式
这时我们出现了SOA及微服务,开始使用注册中心来对各集群实时管理,开始拥有资源调度,治理中心,开始面向服务,将服务进行原子化的彻底拆分。
微服务

1. redis分布式锁的实现

这里我们在如此大的服务中大量使用MySQL的话,效率就会很低,因为MySQL的数据是存储到硬盘的,对硬盘操作,尽管有很多优化但依旧无法满足高并发高效率,所以我们使用redis内存式数据库,数据在内存上操作,速度会快到飞起,这时我们可能就要考虑到安全问题了,就像MySQL一样,大家都知道现在大多都是微服务架构,一个应用会部署很多个进程,如果这些进程同时修改MySQL中的一条数据,为了避免数据出现错误,就要引入分布式锁来保证数据的安全可读。

分布式锁的实现是有很多途径的,可以是一个外部服务来给你上锁,也可以是内部的命令,在现实里,应该redis和zookeeper用的多。

这个分布式锁的功能就是一个请求来调用一条数据,进行上锁,并在使用期间,将过来的其他请求都拒绝。

在redis里我们实现分布式锁是通过内部命令SETNX(set if not exist)来实现,不同的是我们需要先判断一下这条数据是否有锁,没有锁才会上锁,有锁则会请求失败。

setnx lock 1 
(integer) 1 //加锁成功
setnx lock 1
(integer) 0 //加锁失败

当请求使用完这个资源也要及时释放锁,这样其他请求才能再来访问,释放锁我们只要删除掉它即可。

del lock
(integer) 1 //释放成功

实现很简单,但是貌似也存在很大问题!

如果我们一条请求过来访问数据,加上锁,这时出现问题,网络断开或者出现异常,这条请求挂掉了,没有及时释放锁,这条数据不就锁死了???

2.死锁的处理

那其实更简单的方法就是给锁一个计时器即过期时间,到了过期时间,自动释放就好了, Redis同样给我们提供了这个功能

set lock 1 ex 10 nx
OK

10s是过期时间,且为一条命令保证了事务的原子性。
但貌似依旧有问题,很自然就会想到,这个过期时间怎么评估?如果一条请求在使用资源时,锁过期释放了,另一条请求过来,加上锁,开始操作,这时前一条请求刚操作完,默认释放锁,不就释放了正在操作的请求的锁吗?

这里可以看出两个问题:

1.释放别人锁怎么处理
2.过期时间如何评估

3.释放别人锁怎么办?

其实也很简单,本质上还是一条请求拥有释放别人锁的权限,如果每条请求都有自己的锁,且只能释放自己的锁,问题就可以解决了,这个可以通过一个唯一标识来完成,如UUID或者线程的id,上锁时将id标为锁,释放锁时判断锁是否等于自己的id,等于才可以del,但是这里显然不止一条命令,无法保证原子性,即多条命令如果无法同时执行成功,就会出现问题!
这时我们可以用lua脚本写解锁的这个判断过程,并植入redis,因为Redis是单线程,所以执行一个脚本时是不会中断的。释放别人锁的问题就解决了。

4. 过期时间如何评估?

这其实是根据具体需求具体考虑的,但我们还是分析一种大多数情况,我们可以设计一个守护进程,运用心跳机制连接着锁,判断锁快过期了操作还没有执行完,就重新设置过期时间,实现锁的自动续期。

这里redis也帮我们解决了---------Redisson!

这是一个基于java实现的redis SDK的客户端,在使用分布式锁的时候,它采用了自动续期的方案,完美解决了过期时间不好评估的问题。Redisson里面不仅集成了各种锁,可重入锁,乐观锁,红锁等等,非常好用的。

这样分布式就简单实现了。
但是redis真的就没有问题了嘛?前面说的都是单机的情况,而大家都知道,实际应用中我们都是用主从+哨兵的模式来部署的,主库宕机,哨兵会自动故障切换,将从库提升为主库,数据同步,实现可用性。

那么在主从切换的时候,分布式锁显然也可能出现问题,只要是通过多步完成的动作,其中一步出现问题整个就会出现问题。

这里就需要使用Redlock!!!

redis的设计者提出了红锁解决方案,在网上也有不同的讨论,有人支持有人提问有人反对,这里不做过多描述,不过Redlock的实现原理还是很精妙的,推荐大家去找敖丙大佬的博客看一看,很值得思考。

整理不易,如果你喜欢本文的话请多多点赞收藏分享!

最后,学习之路永无止境,大家共勉!

标签:释放,必问,请求,过期,redis,问题,分布式
来源: https://blog.csdn.net/weixin_48444868/article/details/118094090

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有