distributed lock 分布式锁
distributed lock 分布式锁 分布式是一种分布式协调技术,控制分布式系统不同进程共同访问共享资源的一种锁的实现。如果不同的系统或同一个系统的不同主机之间共享了某个临界资源,往往需要互斥来防止彼此干扰,以保证一致性。 分布式锁是由于单机锁无法满足分布式系统锁,在多进程/分布式环境下,需要分布式锁来控制共享内容,保证线程的安全。 为何需要分布式锁 Martin Kleppmann 是英国剑桥大学的分布式系统的研究员,之前和 Redis 之父 Antirez 进行过关于 RedLock (红锁,后续有讲到) 是否安全的激烈讨论。 Martin 认为一般我们使用分布式锁有两个场景: 效率: 使用分布式锁可以避免不同节点重复相同的工作,这些工作会浪费资源。比如用户付了钱之后有可能不同节点会发出多封短信。 正确性: 加分布式锁同样可以避免破坏正确性的发生,如果两个节点在同一条数据上面操作, 比如多个节点机器对同一个订单操作不同的流程有可能会导致该笔订单最后状态出现错误,造成损失。 分布式锁的一些特点 当我们确定了在不同节点上需要分布式锁,那么我们需要了解分布式锁到底应该有哪些特点? 分布式锁的特点如下: 互斥性: 和本地锁一样互斥性是锁最基本的特性, 任意时刻,只有一个客户端能持有锁。 可重入性: 同一个节点上的同一个线程如果获取了锁之后那么也可以再次获取这个锁。 超时释放: 锁失效机制, 防止死锁。正常情况下,请求获取锁之后,处理任务,处理完成之后释放锁。 但是如果在处理任务发生服务异常,或者网络异常时,导致锁无法释放。其他请求都无法获取锁,变成死锁。 为了防止锁变成死锁,需要设置锁的超时时间。过了超时时间后,锁自动释放,其他请求能正常获取锁。 自动续期: 锁设置了超时机制后,如果持有锁的节点处理任务的时候过长超过了超时时间,就会发生线程未处理完任务锁就被释放了, 其他线程就能获取到该锁,导致多个节点同时访问共享资源。对此,就需要延长超时时间。 开启一个监听线程,定时监听任务,监听任务线程还存活就延长超时时间。当任务完成、或者任务发生异常就不继续延长超时时间。 高可用, 高性能: 加锁和解锁需要高效,同时也需要保证高可用防止分布式锁失效,可以增加降级。 安全性: 锁只能被持有锁的客户端释放, 不能被其它客户端释放. 支持阻塞和非阻塞: 和 ReentrantLock 一样支持 lock 和 trylock 以及 tryLock(long timeOut)。即没有获取到锁将直接返回获取锁失败 支持公平锁和非公平锁(可选): 公平锁的意思是按照请求加锁的顺序获得锁,非公平锁就相反是无序的。这个一般来说实现的比较少。 分布式锁一般有三种实现方式: 数据库乐观锁 基于 Redis 的分布式锁 基于 ZooKeeper 的分布式锁 可靠性 首先,为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件: 互斥性。在任意时刻,只有一个客户端能持有锁。 不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。 具有容错性。只要大部分的 Redis 节点正常运行,客户端就可以加锁和解锁。 解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。 Redis 实现分布式锁 Redis 实现分布式锁,性能会比关系式数据库高一些. ...