分布式锁,是单机锁的一种扩展,主要是为了锁住分布式系统中不一样机器代码的物理块或逻辑块。以此保证不一样机器之间的逻辑一致性。
伪代码以下算法
if (能够插入一条数据) { lock { if (能够插入一条数据) { // 插入一条数据 } } }
正常代码流程图(markdown画的,有点丑)设计模式
st=>start: 项目启动 watcher=>operation: 监听etcd ed=>end: 等待请求 st->watcher->ed
st=>start: 开始执行lock ed=>end: 结束 watcher=>operation: 监听etcd hasEvent=>condition: 事件队列为空 pushEvent=>operation: 争夺锁事件 入等待队列 watcherEvent=>operation: etcd节点超时事件和释放事件 popEvent=>operation: 争夺锁事件 出事件队列 execute=>operation: 执行被锁住的代码块 fight=>condition: 争夺锁失败 unlock=>operation: 释放锁 st->fight fight(no)->execute->unlock->ed fight(yes)->pushEvent->watcherEvent->popEvent->fight
事件细节伪代码缓存
准备一个清空全部相关事件的万能方法服务器
假设eventQueue是这种业务对应的事件队列 假设fightEvent是该次执行的争夺锁事件 假设clear为清除超时事件的方法 假设holdEvent为持有锁超时事件 假设waitEvent为等待锁超时事件 假设unLockEvent为释放锁事件 // 清空全部事件 - clearAll eventQueue.remove(fightEvent) clear(waitEvent) clear(holdEvent)
监听etcd的两个事件markdown
// 当etcd锁超时事件或etcd主动释放事件发生时 // 争夺锁事件 出事件队列 fightEvent = eventQueue.pop // 执行争夺锁事件 执行 fightEvent
争夺锁事件多线程
// 争夺锁事件 执行 etcd争夺锁方法 if (抢到锁了) { // 清空全部事件 执行 clearAll // 设置持有锁超时事件 设置 holdEvent } else { // 争夺锁事件若是是二次入队列,建议到队列头,而不是到队列尾 eventQueue.push(fightEvent) }
等待锁超时事件(用时间轮延时执行)分布式
// 清空全部事件 执行 clearAll // 抛出异常 throw new Exception
持有锁超时事件(用时间轮延时执行)spa
// 执行释放锁事件 执行 unLockEvent
释放锁事件线程
// 释放锁事件 执行 etcd释放锁方法 // 清空全部事件 执行 clearAll
备注设计
以上代码能够用有限状态机设计模式来设计业务
图解分布式服务器与etcd集群交互
补充说明