type
status
date
slug
summary
tags
category
titleIcon
password
icon
calloutIcon
自定义分布式锁,解耦业务代码与通用锁管理部分。
节选自:
分布式锁,自定义AOP,Redisson,设计模式,SPEL
这一部分在视频里完全没提,第二版飞书文档的Day11里有部分讲解,以下做理论部分要点精简+代码部分分析。
分布式锁
- 引入背景:Synchronized单机锁基于JVM的Monitor实现,在集群下多个JVM意味着多个Monitor,无法达到互斥的效果,需要在多个实例外设置同一把锁,即分布式锁。
- Redis实现分布式锁的可能性:1.Redis可以被多JVM实例共享访问;2.SETNX互斥命令;3.DEL释放锁;4.单线程执行命令(串行)
- Redis直接实现分布式锁与可能遇到的问题:
- 直接实现:SET lock thread1 NX EX 20,主要包括两步
- 1.超时释放:锁不一定正常释放(实例宕机),可导致死锁,需要设置过期时间(例中上锁与超时设置操作保持原子性)
- 2.存入标识:存入自身线程标识,删除时如果仍是自身标识才可删除,防止锁误删(避免不了)(图源:‣)
- 1.超时问题:WatchDog机制,锁成功开定时任务,锁到期前自动续期避免超时释放,同时宕机后一同停止,避免死锁
- 2.原子性问题:Lua脚本
- 3.锁重入:类似Synchronized,可使用Hash记录持有者与重入次数,次数0时删除
- 4.主从同步延迟:RedLock
- 5.锁失败重试


但判断与删除不是原子的,仍可能误删

超时释放难以避免锁误删,锁的操作需要原子性,主从同步存在延迟,同一线程无法多次获取同一锁可能死锁,所以需要解决:
成熟解决方案:Redisson
Redisson Quick Start
maven引入
配置类与自动装配
ConditionalOnClass自动装配,引入Redisson依赖时配置才生效
入参的RedisProperties来源:


resources/META-INF/spring.factories:
基本使用
场景实例
- waitTime:获取锁的等待时间。当获取锁失败后可以多次重试,直到waitTime时间耗尽。waitTime默认-1,即失败后立刻返回,不重试。
- leaseTime:锁超时释放时间。默认是30,同时会利用WatchDog来不断更新超时时间。需要注意的是,如果手动设置leaseTime值,会导致WatchDog失效。
- TimeUnit:时间单位
通用分布式锁AOP
避免通用的非业务代码对业务的侵入
通过注解标记切入点,同时传递锁参数(名称(解析SPEL表达式得到动态名);等待时间;超时时间;时间单位)
注解
切面
注:原代码里缺少了Ordered接口实现,可能会导致优先级跟@Transactional冲突,无法保证锁边界大于事务边界,这里代码补上,其中Orderded接口的getOrder方法用于获取AOP切面执行优先级(越小越优先),事务@Transactional的默认是Integer.MAX_VALUE(参见org.springframework.transaction.annotation.EnableTransactionManagement)

顺带一提,在org.springframework.context.annotation.ConfigurationClassUtils下也能见到类似的东西,不过是用于@Configuration配置类的

枚举
锁类型枚举(策略模式)
也可使用简单工厂模式(写法2)
EnumMap纯用数组实现,可能比HashMap更快
Implementation note: All basic operations execute in constant time. They are likely (though not guaranteed) to be faster than their HashMap counterparts.
实际上在业务里也有相关使用,优惠劵折扣策略里
锁失败策略(策略模式)
waitTime参数决定重试时间,没有不重试
业务AOP版本
防止兑换优惠劵业务超卖效果展示
- 选择目标优惠劵

- 设置jmeter参数


- 运行结束,检查Redis 100条√ 1人1张√ 0剩余√


- 检查数据库 100√

- 检查汇总报告 √

- 检查jmeter报告搜索仅100请求成功 √

- 检查请求失败原因 优惠卷库存不足√ 请求超时(分布式锁获取超时)√



- 与策略一致 √

代码:
领取优惠劵


兑换优惠劵

- 作者:CamelliaV
- 链接:https://camelliav.netlify.app/article/lock-aop
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。