分布式锁初体验

???

单体服务我们用synchronized或者用ReentrantLock等等方法就可以很好的控制并发,但是在分布式部署下那样做就不行了- -,所以我们需要引入分布式锁。

基于数据库的分布式锁

这个用的应该不多,大致就是利用数据库的行锁select xxxx for update

基于redis的分布式锁

这个就是利用redis的set nx px

springboot实现大致如下(相信聪明的你是能看懂的!)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//setIfAbsent
Boolean ifAbsent = redisTemplate.opsForValue()
.setIfAbsent(key
, value
, expireTime
, TimeUnit.SECONDS);
//判断是否拿到锁
if(ifAbsent) {
try {
proceed = joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
} finally {
String redisScriptStr = "if redis.call(\"get\",KEYS[1]) == ARGV[1] then\n" +
" return redis.call(\"del\",KEYS[1])\n" +
"else\n" +
" return 0\n" +
"end";
RedisScript<Boolean> redisScript = RedisScript.of(redisScriptStr,Boolean.class);
Boolean result = (Boolean) redisTemplate.execute(redisScript, Arrays.asList(key), value);
if(result) {
log.info("释放锁");
}else {
log.info("释放锁失败");
}
}
}

基于zookeeper的分布式锁

这里建议直接使用Apache Curator,这个是升级版zookeeper客户端,里面封装了分布式锁的方法。

1
2
3
4
5
6
7
8
9
10
11
12
InterProcessMutex lock = new InterProcessMutex(client, lockPath);
if ( lock.acquire(maxWait, waitUnit) )
{
try
{
// do some work inside of the critical section here
}
finally
{
lock.release();
}
}

看官网给的示例,多方便- -

基于Redisson的分布式锁

redisson跟jredis一样,都是redis客户端,据说redisson更强- -封装了更多东西。

1
2
3
4
5
6
7
log.info("进入方法");
RLock redissonLock = redissonClient.getLock("redissonLock");
redissonLock.lock(30,TimeUnit.SECONDS);
log.info("拿到锁执行");
Thread.sleep(6000);
redissonLock.unlock();
log.info("释放了锁");

使用redisson提供的分布式锁也是极其方便

上面说的redisson跟curator自己去找他的依赖加上就好了,推荐使用别人封装好的- -除非你觉得你比他强!

end…