一、锁的业务场景
1、为什么要加锁?
在多线程环境下,针对一些共享资源往往会出现线程安全问题,需要加锁校准程序执行过程。
2、单机锁的类型
synchronized 关键字。
Lock 接口的锁。
atomic 包的封装类。
3、分布式场景中的锁
在分布式系统中,如果只是在一台服务器内对某个资源加锁,但是无法对其他服务器生效,数据安全问题还是存在。
4、分布式锁的类型
MySQL ------ 加锁语句
Redis ------ Lua脚本写分布式锁
ZooKeeper ----- 分布式锁
二、MySQL实现分布式锁
// 使用MySQL的排他锁
select * from table where id = ABC for update;
优点是可以很轻松地编写代码实现分布式锁。
缺点是在分布式场景下容易造成长时间的锁等待,导致系统性能下降严重。并且需要手动控制事务,代码编写繁琐,并且会进一步延长锁等待的时间。
三、Redis实现分布式锁
1、手动实现分布式锁
加锁:set key threadId ex time nx
解锁:LUA脚本 -> 先get key,对比threadId,再del key。
2、Redisson
使用Redisson可以快速简单地使用一个分布式锁。
3、RedLock
红锁是redis推出的一个应对极端情况的分布式锁,要求最少有五台redis节点,并且在锁过期时间内最少有三台返回成功,才能获取锁。
优点:更加健壮、即使在加锁过程中出现了一台redis掉线了,也不会影响主业务流程。
缺点:配置繁琐,无法避免分布式环境的NPC问题。
N:网络延迟。
P:进程暂停。如果恰好某一台redis服务器出现了GC处理,就会导致进程暂停。
C:时钟漂移。无法确保每一台redis服务器的时间一致。
四、Zookeeper中实现分布式锁
1、依靠ZK节点类型中的临时序号节点实现。
临时节点有过期时间,避免死锁。