分布式锁的实现

"distributed lock"

Posted by yueLng on 2019-12-13

In computer science, a lock or mutex (from mutual exclusion) is a synchronization mechanism for enforcing limits on access to a resource in an environment where there are many threads of execution. A lock is designed to enforce a mutual exclusion concurrency control policy.

操作系统的锁

  • 硬件:对于单处理器而言,临界区问题好解决:修改共享变量时禁止中断出现。对于多处理器需要计算机系统提供特殊硬件指令以允许能原子地(不可中断地)检查和修改字的内容或交换两个字的内容(比如CAS,compare and swap)
  • 软件:信号量,一个信号量可以为0(没有保存下来的唤醒次数)或者为正值(表示一个或多个唤醒操作),每个信号量关联一个等待进程列表,如果wait时发现信号量不为正则选择忙等,或者阻塞,进程加入到等待链表,signal()时从等待链表取出进程唤醒。
  • 锁的种类:互斥所、自旋锁、读写锁(无模式、读模式、写模式)

使用cas实现自旋锁

1
2
3
4
5
6
7
8
9
10
11
12
13
type SpinLock struct {
count uint64
}
func (l *SpinLock) Lock() {
//不断地尝试原子地更新l.count的值,直到操作成功为止
for !atomic.CompareAndSwapUint64(&l.count, 0, 1) {
}
}
func (l *SpinLock) Unlock() {
//在原子地存储某个值的过程中,任何CPU都不会进行针对同一个值的读或写操作。
//原子的值存储操作总会成功,因为它并不会关心被操作值的旧值是什么
atomic.StoreUint64(&l.count, 0)
}

Chubby

分布式锁包含三个基本问题,分别是一致性协议、分布式锁的实现、分布式锁的使用

  • 一致性协议:chubby采用有强主的Multi-Paxos,参考Paxos Made Simple
  • 分布式锁的实现:

How to do distributed locking

这篇文章主要讨论了由Redlock开始,分布式锁的基本解决办法,

  • 锁的基本目标,效率与正确性。
  • 分布式锁存在的问题,未能正确处理分布式锁的租期问题。
  • 一种解决方案是为每次获得锁都带上token,只接受最新的token,拒绝旧的token
  • 使用时间来确定一致性是不科学的,分布式算法不应该依赖任何时间,做任何时间假设

>
分布式锁是有租期的,某服务在获取分布式锁之后,进行操作,然后这操作耗时大于锁的过期时间,如果执行操作不知道自己已经过期,就会引起相应的问题。
是获得分布式锁的同时是否需要加入特定的机制,如果未在过期时间内完成操作,则将整个过程置为失败

参考资料

lock wikipedia
基于Redis的分布式锁到底安全吗(上)
Redis实现分布式锁
Redis RedLock 完美的分布式锁么?
用redis构建分布式锁
golang实现redis分布式锁-GitHub
etcd-lock
distrilock
Chubby的锁服务