前言
最近开发公司的项目,遇到了分布式的场景,即,同一条数据可能被多台服务器或者说多个线程同时修改,此时可能会出现分布式事务的问题,随即封装了redis分布式锁的注解。
场景分析
前提:我的银行卡有0元钱,现在有A,B两个人,想分别给我转10元钱
分析:
假如A,B通过读数据库,同时发现我的余额是0,这时,
线程A,会给我设置:
余额 = 10 + 0
线程B,会给我设置:
余额 = 10 + 0
最后,我的卡上收到了两个人的转账,但是最后金额居然只有10元!!这是怎么回事?
其实原因就在于多个线程,对一条数据同时进行了操作。如果我们可以设置一下,在修改的方法上面加一个锁,每次修改之前,(A)先拿到这个锁,再去做修改方法,此时,其他(B)线程想要修改的时候,看到锁已经不再,需要等待锁释放,然后再去执行,就保证了A,B先后依此执行,数据依此累加就没问题了。
解决办法
基于代码的可移植性,我将分布式锁做成了注解,大家如果有需要,可以直接将jar包拿过去做相应的修改即可,jar包下载地址(链接:https://pan.baidu.com/s/1hBn-...
提取码:1msl):
注解使用说明:
1.在需要添加分布式锁的方法上面加上@RedisLock
如果key不添加,则默认锁方法第一个参数param的id字段,如果需要指定锁某个字段,则@RedisLock(key = "code")
2.如果方法没有参数,则不可使用RedisLock锁
@RedisLock
public void updateData( Data param){
}
下面详细分析一下封装的源码:
先看一下项目结构(总共就4个类):
//RedisLock注解类:没什么好解释的
/**
* Created by liuliang on 2018/10/15.
*/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisLock {
//被锁的数据的id
String key() default "";
//唤醒时间
long acquireTimeout() default 6000L;
//超时时间
long timeout() default 6000L;
}
//----------------------类分割线---------------------
//RedisService 一个简单的操作redis的类,封装了加锁和释放锁的方法
/**
* Created by liuliang on 2018/10/15.
*/
@Service
public class RedisService {
@Autowired
StringRedisTemplate stringRedisTemplate;
@Resource(name = "stringRedisTemplate")
@Autowired
ValueOperations valOpsStr;
@Autowired
RedisTemplate redisTemplate;
@Resou