Java基于Spring AOP+Redis+注解实现适用多种场景的分布式锁

分布式系统开发中常常用到分布式锁,比如防止多个用户同时预订同一个商品,传统的synchronized就无法实现了,而基于数据库的乐观锁实现又可能会对数据库产生较大的压力。而分布式锁相对较轻量,对性能影响也较小。目前主流的分布式锁都基于Redis实现。使用分布式锁的流程一般如下:
在这里插入图片描述
如果需要使用分布式锁的地方有多个,那么就需要写多个类似的代码。而重复代码是开发中最常见到的 bad smell 。我们可以使用 AOP 把这段逻辑抽象出来,这样就避免了重复代码,也极大地减去了工作量。

目标

  • 对业务代码无侵入(或侵入性较小)
  • 使用方便
  • 对性能影响小
  • 易维护

方案

  1. 使用注解(假设注解为@Lock)声明要使用分布式锁的业务method、要锁定的对象(一般是业务主键)、失效时间等信息。在这里插入代码片
  2. 使用Spring AOP arround(环绕通知)增强被@Lock注解的方法,把前面提到的”使用分布式锁的流程“逻辑抽象到切面中。
  3. 使用Redis实现分布式锁。一般是基于string类型的set命令实现。

难点

  1. 如何根据请求的不同,锁定不同的对象
    可以使用 Spring EL 表达式指定锁定对象,加锁时根据业务方法参数值、参数名称解析表达式,得出要加锁的对象(Redis string的key)。
  2. 分布式锁该如何选择
    • 可以选择自己实现(加锁使用set命令即可,解锁需要使用lua脚本保证命令的原子性,先判断锁是否仍有效、是否由当前线程加锁,是的话才能通过del来解锁)。
    • 也可以选择使用redisson等第三方库。使用方式可以参考官方示例:Spring版/Spring Boot版

优点

使用时只需在业务方法上加一个注解就可以了,使用灵活、开发效率高、侵入小、适用性强。业务方法只需专注于业务代码,可读性强,易维护。

适用场景

  • 防止并发修改
  • 防止重复提交
  • 幂等校验
  • ……

实现

1. 引入包

Spring Boot方式
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
  <groupId>org.redisson</groupId>
  <artifactId>redisson-spring-boot-starter</artifactId>
  <version>3.12.5</version>
</dependency>
Spring 方式
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-aop</artifactId>
  <version>5.1.3.RELEASE</version>
</dependency>
<dependency>
  <groupId>org.aspectj</groupId>
  <artifactId>aspectjweaver</artifactId>
  <version>1.9.2</version>
</dependency>
<dependency>
  <groupId>org.redisson</groupId>
  
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值