孤尽班第十二次课-Redis分布式锁

孤尽班第十二次课-Redis分布式锁

分布式锁简介

在同一个JVM 内部,大家往往采用synchronized 或者Lock 的方式来解决多线程间的安全问题,但是在分布式架构下,在JVM 之间,那么就需要一种更佳高校的锁机制,来处理这种跨JVM 进程之间的线程安全问题,解决方案就是: 使用分布式锁。
在这里插入图片描述

Redis 原理解析

Redis 分布式锁原理
Redis 分布式锁机制,主要借助setnx 和 expire 两个命令完成。 
1. setnx  当key 不存在,将key 设置为value, 存在不做任何操作,返回0. 
2. expire 设置key 过期时间。
原理解析:
3. key 不存在时创建,并设置value 和过期时间,返回值为1, 成功获取到锁。
如key 存在时直接返回0,抢锁失败。
持有锁的线程释放锁时,手动删除key, 或者过期时间到,key 自动删除,锁释放。
set key value[Ex seconds] [PX millisecomds] [NX|XX] 
EX  second:  设置失效时长, 单位秒
milliseco 失效 nds:  设置时长,单位毫秒 
key  不存在时设置value, 成功返回OK ,失败返回nil 
XX   key 存在时设置valuem, 成功 返回OK ,失败返回nil
Redis 中使用Lua
EVAL: 对Lua 脚本进行求值,命令如下:
EVAL script numkeys key [key.......] arg [arg....]
1. script : 参数是一段Lua.5.1 脚本程序 。它会被运行在Redis 服务器上下文中。
2. numkeys: 参数用于指定键名参数的个数。

# 在Lua 脚本中可以使用redis.call() 函数来执行Redis 命令
## 这段脚本的确实现了将键foo 的值设为bar
eval "return redis.call('set',KEYS[1],ARGV[1])" I foo bar 
> OK 
Jedis 分布式锁实现

加锁: 就是调用SET key PX NX 命令

 set key value [EX seconds]  [PX millseconds] [NX|NX] 
 key 加锁的key
 value UUID.randomUUID().tostring(). 代表加锁的客户端请求标识。
 nxxx nx 表示SET IF NOT EXIS 可以使用T 
 expx PX 表示毫秒
 time: 表示过期时间
锁过期问题

预估业务操作10 秒, 锁设置20秒。 各种原因,比如STW 业务操作执行超过20秒 了, 业务会在无锁状态下运行,就会发生数据紊乱。
注: STW : java 中 Stop - The- World 机制简称STW, 常发生于fullGC 这时Java 应用程序的其他所有线程都被挂起(除了垃圾收集器之外)
在这里插入图片描述

  1. 乐观锁方式 增减版本号。
  2. watch dog 自动延期
 锁过期解决方案:
 乐观锁:  增加版本号需要调整业务逻辑。与之配合,所以会入侵代码。

在这里插入图片描述
Watch dog 自动延期机制
不会侵入业务代码,redisson就是 采用这种解决方案。

 客户端1 加锁的key  默认生存时间才30秒, 如果超过了30 秒, 客户端1 还想一直持有这把锁,怎么办呢? 只要客户端1 一旦加锁成功,就会启动一个watch dog  看门狗,他是后台一个线程,会每隔10 秒检查一下,如果客户端1 还持有锁key, 那么就会不断的延长锁key 的生存时间。

Redisson 分布式锁

  • Redisson 简介
    Redisson 是 基于 Netty的Redis 客户端。不但能操作原生的Redis 数据结构,还为使用者提供了一系列具有分布式特性的常用工具类,实现了分布式锁。
    在这里插入图片描述
    Redisson 分布式锁
    Redis 分布锁 和 JUC 的Lock 方法相似。RLock 接口继承了Lock 接口, 代码如下。
    在这里插入图片描述
    锁的存储结构:
    锁的结构式Hash
key: 锁的名字
字段: UUID+ threadid 
值:  表示重入的次数
Redisson 分布锁原理
 **加索**
 1. 判断有没有 “DISLOCK” 
 2. 如果没有,设置UUID:1 = 1
 3.  设置它的过期时间
 锁重入 
 4.  key 和字段都存在,锁重入
 5. 执行命令incrby UUID:1 1
 6. 结果:DISLOCK: {UUID: 1 2}
 锁互斥
 1 .客户端2 进入
 7. 判断有KEY,没有字段 
 8. 返回过期时间
 9. 客户端2  自旋等待 

在这里插入图片描述

释放锁
	1. 判断KEY 是否存在
	2. 如果不存在,返回nil
	3. 如果存在,使用hincryby -1  减  1 
	4. 减完后m, count > 0 值 仍大于0 则返回0  
	5. 减完后 ,count <= 0 ,则删除key 
	6. 用publish 广播锁释放消息

在这里插入图片描述

Watch dog 自动延期

watch dog 当加锁成功后,同时开启守护线程,默认有效期是30 秒,每隔10秒就会给锁延续期到30秒

  • watch Dog 只有 在未显示指定加锁时间才会生效
  • lockWatchdog Timeout 可以设置超时时间

在这里插入图片描述

分段锁

这是雪松老师的思想设计

可以使用分段的方式(思想来源) map / reduce , ConcurrentHashMap ),以空间换时间。为了达到每秒600 个 订单, 可以将锁 分成 600/ 5 = 120 个 段  反过来, 每个段1 秒可以操作5 次, 120 个段, 合起来, 每秒操作600  次。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值