redis分布式锁

前言

写博客是自己对知识梳理,目前是写给自己看,算是自己学习后的作业,也是为了养成一个良好的习惯。


一、分布式锁简介

1. 为什么要使用锁?
	使用锁的目的就是保证即便是在多线程下同一时间只有一个客户端可以对共享资源进行操作。
	它解决的资源竞争的问题,如java常见锁就有Synchronized和lock等。
2. 为什么要使用分布式锁?
	由于java常见的锁如Synchronized和lock等锁都是基于JVM的,在分布式环境下就失效了,如是便有了分布式锁来解决资源竞争问题。

二、分布式锁技术

主流实现分布式锁的技术:
1. 基于关系型数据库实现的分布式锁
	利用mysql的乐观锁实现分布式锁(版本号),但是性能完全基于mysql本身,在高并发会直接打垮mysql,用的时候一定要三思!!(由于性能太差,不推荐,也不做后续的对比)
2. 基于单机redis实现分布式锁
	redis2.6后 SET指令已经支持nx/px/expire,实现加锁非常简单,也是目前99%中小型公司分布式锁的选择。
3. 基于redis集群实现的分布式锁
	为了解决单机redis分布式锁的单点故障及可重入性问题,redis推出了红锁。
4. 基于zk集群实现的分布式锁
	利用zk有序的临时节点加上它的watch机制实现分布式锁,它的可靠性最高。

对于以上分布式锁实现的对比:
	1. 基于关系数据库的分布式锁,一定要在没有大流量的业务且没有其他资源下才会去选择它;
	2. 实现复杂度:234都有对应的客户端,相应的功能已经都封装好,都非常简单;
	3. 可靠性(高--低):zk集群 > 红锁 > 单机redis;
	4. 性能(高--低):单机redis > 红锁 > zk集群;
	5. 成本(高--低):红锁 > zk集群 > 单机redis;

基于以上的对比,也不难发现为什么99%中小型公司的分布式锁要选择 单机redis。

三、redis分布式锁实现

加锁过程:
	redis的加锁就是给Key键设置一个值,且key存在时则不能设置成功,为避免死锁,并给定一个过期时间,
且在redis 2.6 后SET指令已经支持nx/px/expire,它能保证设置key和给key加过期时间的原子性。

具体实现:
	SET(key,value,NX,PX,time)
其中 key 就是要锁定的资源;value 可以是客户端唯一标识;NX代表只在键不存在时,
才对键进行设置操作;PX 表示对这个key要设置过期时间 ;time 表示key过期的具体时间。
解锁过程:
	就是删除掉key来释放资源,但是不能乱删除,需要通过判断key中的value和当前客户端标识一致时才能删除,且整个过程要保证它的原子性。
	为什么解锁过程要保证原子性呢?
	举例说明一下如果解锁过程没有保证原子性的问题,当v1客户端进来拿到锁了,当它准备解锁时在判断客户端标识时拿到value是v1即客户端标识一致,
此时刚好它加锁的key过期了,同时v2客户端加锁成功了,则v1会删除属于v2的key,这种情况下就属于误删,则解锁的过程必须要保证原子性。
	那么如何保证加锁过程保证原子性?
	使用lua脚本,在lua脚本中的指令可以保证它的原子性执行。(lua脚本也不支持回滚,但可以手动回滚)
	
	
解锁的lua脚本如下:
-------------------------------------------------------
if redis.call('get',KEYS[1]) == ARGV[1] then 
   return redis.call('del',KEYS[1]) 
else
   return 0 
end
-------------------------------------------------------

四、redis分布式锁问题

基于以上分析,我们来总结一下它的问题:
1. 单点故障问题,由于是单机redis,一旦宕机了那么锁就失效了;
2. 可重入性,即key过期时间不好评估,时间设置长了性能就低了,时间设置短了又存在加锁期间业务没处理完锁就失效的问题;
3. 分布式锁本质上还是悲观锁会阻塞,在设计时要考虑到这点,它会降低系统的吞吐量。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值