孤尽T31项目Day24

孤尽T31项目Day24

Redis分布式锁

1 分布式锁简介

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

2 Redis 分布式锁分析

2.1 Redis 分布式锁原理

Redis 分布式锁机制,主要借助setnx 和 expire 两个命令完成。

  1. setnx 当key 不存在,将key 设置为value, 存在不做任何操作,返回0.
  2. expire 设置key 过期时间。
    原理解析:
  3. key 不存在时创建,并设置value 和过期时间,返回值为1, 成功获取到锁。
  4. 如key 存在时直接返回0,抢锁失败。
  5. 持有锁的线程释放锁时,手动删除key, 或者过期时间到,key 自动删除,锁释放。

在这里插入图片描述
set同时设置过期时间命令

set key value[Ex seconds] [PX millisecomds] [NX|XX] 

EX second: 设置失效时长, 单位秒
PX milliseco 失效 nds: 设置时长,单位毫秒
NX key 不存在时设置value, 成功返回OK ,失败返回nil
XX key 存在时设置valuem, 成功 返回OK ,失败返回nil

2.2 Redis 中使用Lua

EVAL: 对Lua 脚本进行求值,命令如下:

EVAL script numkeys key [key.......] arg [arg....]
  1. script : 参数是一段Lua.5.1 脚本程序 。它会被运行在Redis 服务器上下文中。
  2. numkeys: 参数用于指定键名参数的个数。

CALL: 在Lua 脚本中可以使用redis.call() 函数来执行Redis 命令。
这段脚本的确实现了将键foo 的值设为bar

> eval "return redis.call('set',KEYS[1],ARGV[1])" I foo bar 
> OK 

2.3 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: 表示过期时间

2.4 锁过期问题

预估业务操作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 的生存时间。

3 Redisson 分布式锁

3.1 Redisson 简介

Redisson 是 基于 Netty的Redis 客户端。不但能操作原生的Redis 数据结构,还为使用者提供了一系列具有分布式特性的常用工具类,实现了分布式锁。

3.2 Redisson 分布式锁

Redis 分布锁 和 JUC 的Lock 方法相似。RLock 接口继承了Lock 接口.
锁的结构式Hash:
key: 锁的名字
字段: UUID+ threadid
值: 表示重入的次数

3.3 Redisson 分布锁原理

加锁

  1. 判断有没有 “DISLOCK”
  2. 如果没有,设置UUID:1 = 1
  3. 设置它的过期时间
    锁重入
  4. key 和字段都存在,锁重入
  5. 执行命令incrby UUID:1 1
  6. 结果:DISLOCK: {UUID: 1 2}
    锁互斥
  7. 客户端2 进入
  8. 判断有KEY,没有字段
  9. 返回过期时间
  10. 客户端2 自旋等待
    在这里插入图片描述

3.2.1 释放锁

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

在这里插入图片描述

3.3 Watch dog 自动延期

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

watch Dog 只有 在未显示指定加锁时间才会生效
lockWatchdog Timeout 可以设置超时时间
在这里插入图片描述

4 分段锁

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值