Redis的锁
2021/9/19 19:36:03
本文主要是介绍Redis的锁,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
redis的锁分为乐观锁和悲观锁。
一、悲观锁(分布式锁)
这里解释一下,普通锁和分布式锁的区别:
1.普通锁:synronize和lock,处理的是单节点(一个进程)多线程并发的问题,保证数据安全;
2.分布式锁:redis, zk, mysql的分布式锁,处理的是多个节点的多个进程并发的安全问题
1.为什么需要分布式锁
多个进程,需要同时操作一个共享资源,需要达到互斥的效果。
2.分布式锁如何实现
SET lock_key $unique_id EX $expire_time NX
通过一条指令设置锁过期时间,保证原子性.
锁过期时间不好评估,该如何?
加锁时,先设置一个过期时间,然后我们开启一个「守护线程」,定时去检测这个锁的失效时间,如果锁快要过期了,操作共享资源还未完成,那么就自动对锁进行「续期」,重新设置过期时间。(Redisson已封装好了,直接用)
小结:
- 死锁:设置过期时间
- 过期时间评估不好,锁提前过期:守护线程,自动续期
- 锁被别人释放:锁写入唯一标识,释放锁先检查标识,再释放
3.集群模式下,是否依旧安全?
在使用 Redis 时,一般会采用主从集群 + 哨兵的模式部署,当主库异常宕机时,哨兵可以实现「故障自动切换」。
试想这样的场景:
客户端 1 在主库上执行 SET 命令,加锁成功
此时,主库异常宕机,SET 命令还未同步到从库上(主从复制是异步的)
从库被哨兵提升为新主库,这个锁在新的主库上,丢失了!
怎么办?。。。
解决方案:RedLock(红锁)
4.RedLock的操作过程
整体的流程是这样的,一共分为 5 步:
(1)客户端先获取「当前时间戳T1」
(2)客户端依次向这 5 个 Redis 实例发起加锁请求(用前面讲到的 SET 命令),且每个请求会设置超时时间(毫秒级,要远小于锁的有效时间),如果某一个实例加锁失败(包括网络超时、锁被其它人持有等各种异常情况),就立即向下一个 Redis 实例申请加锁
(3)如果客户端从 >=3 个(大多数)以上 Redis 实例加锁成功,则再次获取「当前时间戳T2」,如果 T2 - T1 < 锁的过期时间,此时,认为客户端加锁成功,否则认为加锁失败
(4)加锁成功,去操作共享资源(例如修改 MySQL 某一行,或发起一个 API 请求)
(5)加锁失败,向「全部节点」发起释放锁请求(前面讲到的 Lua 脚本释放锁)
总结,有 4 个重点:
(1)客户端在多个 Redis 实例上申请加锁
(2)必须保证大多数节点加锁成功
(3)大多数节点加锁的总耗时,要小于锁设置的过期时间
(4)释放锁,要向全部节点发起释放锁请求
关于NPT难题
- 网络异常,网络延迟
- 进程暂停
- 时钟漂移
参考文章:https://mp.weixin.qq.com/s/ybiN5Q89wI0CnLURGUz4vw?_share_channel=wechat
二、乐观锁(Watch机制)
关键词:watch(盯住), multi(开始), exec(执行)
原理:
1.watch在事物开始之前盯住一个或多个变量
2.在执行(exec)事物队列时,会检查关键变量自watch之后是否被修改了
3.如果被修改了,则返回null,执行失败,客户端一般选择重试。
这篇关于Redis的锁的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-08阿里云Redis项目实战入门教程
- 2024-11-08阿里云Redis资料:新手入门与初级使用指南
- 2024-11-08阿里云Redis教程:新手入门及实用指南
- 2024-11-07阿里云Redis学习入门:新手必读指南
- 2024-11-07阿里云Redis学习入门:从零开始的操作指南
- 2024-11-07阿里云Redis学习:初学者指南
- 2024-11-06阿里云Redis入门教程:轻松搭建与使用指南
- 2024-11-02Redis项目实战:新手入门教程
- 2024-10-22Redis入门教程:轻松掌握数据存储与操作
- 2024-10-22Redis缓存入门教程:快速掌握Redis缓存基础知识