1.什么是分布式锁?为什么要使用分布式锁?

首先,我们要清楚为什么要使用锁。如果在多线程高并发的情况下,不使用锁,可能会带来线程安全的问题。就比如12306卖票,不使用锁可能会导致票超卖的问题。
java提供的sync,lock都是本地锁,只能保证本地线程的线程安全。如果涉及到分布式,运行在不同客户端上,有多个jvm,可能语言都不同,那本地锁就做不到了,这个时候就需要使用到分布式锁技术。

2.分布式锁有几种实现方式?应该如何选用。

1.通过数据库实现
①悲观锁。分为共享锁和排他锁(S锁和X锁)
②乐观锁。通过一个version字段,来判断。如果低于当前version版本则不让修改
③通过数据库表实现。创建一张lock表,锁唯一标识就是主键id,这样如果有了锁,别个线程就不能再插入。

2.通过redis实现
①通过redis原生操作实现。setnx
②通过redisson实现。redisson内部帮我们封装好了lua脚本,并提供了种类繁多的锁供我们使用。
(redis相关详见Redis面试题)

3.通过ZooKeeper实现
因为ZooKeeper同一个路径下不能同名的节点。利用这个特性,我们就可以用来实现分布式锁。
ZooKeeper的节点可以分为四种:持久节点,持久有序节点。临时节点,临时有序节点。
①通过Zookeeper原生的方式实现。
②通过curator来实现(类似于Redisson来操作Redis)

如果项目中使用了ZK当注册中心,则选用ZK实现分布式锁。如果没有,则选Redis。切莫多引入一个中间件,会降低系统性能。
数据库表的方式基本不用,实现太过于麻烦,而且基于数据库实现,效率并不高。但是乐观锁和悲观锁经常会和Redisson等连用。乐观锁最为常用,对有竞争的数据都会加version字段。