服务端开发实战Java技术升华Spring boot

分布式锁解决并发的三种实现方式

2018-08-31  本文已影响17人  AKyS佐毅

分布式锁解决并发的三种实现方式

分布式锁应该是怎么样的

1、数据库锁

1.1、乐观锁

2、基于redis的分布式锁

-首先,为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件:

可以看到,我们加锁就一行代码:==jedis.set(String key, String value, String nxxx, String expx, int time)==,这个set()方法一共有五个形参:

总的来说,执行上面的set()方法就只会导致两种结果:1. 当前没有锁(key不存在),那么就进行加锁操作,并对锁设置个有效期,同时value表示加锁的客户端。2. 已有锁存在,不做任何操作。

加锁代码满足我们可靠性里描述的三个条件。首先,set()加入了NX参数,可以保证如果已有key存在,则函数不会调用成功,也就是只有一个客户端能持有锁,满足互斥性。其次,由于我们对锁设置了过期时间,即使锁的持有者后续发生崩溃而没有解锁,锁也会因为到了过期时间而自动解锁(即key被删除),不会发生死锁。最后,因为我们将value赋值为requestId,代表加锁的客户端请求标识,那么在客户端在解锁的时候就可以进行校验是否是同一个客户端。由于我们只考虑Redis单机部署的场景,所以容错性我们暂不考虑。

==错误实例==

  ![image](https://img.haomeiwen.com/i325120/3b86accd18c5a9d1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

  setnx()方法作用就是SET IF NOT EXIST,expire()方法就是给锁加一个过期时间。乍一看好像和前面的set()方法结果一样,然而由于这是两条Redis命令,不具有原子性,如果程序在执行完setnx()之后突然崩溃,导致锁没有设置过期时间。那么将会发生死锁。网上之所以有人这样实现,是因为低版本的jedis并不支持多参数的set()方法。

3、基于Zookeeper实现分布式锁

4、三种方案的比较

在实践中,当然是从以可靠性为主。所以首推Zookeeper。

145天以来,Java架构更新了 428个主题,已经有91位同学加入。微信扫码关注java架构,获取Java面试题和架构师相关题目和视频。上述相关面试题答案,尽在Java架构中。

上一篇下一篇

猜你喜欢

热点阅读