1.基本概念分布式锁是单机锁的扩展,主要是对分布式系统中不同机器码的物理或逻辑块进行加锁。这确保了不同机器之间的逻辑一致性。2.一个简单的caseDB写操作的double-checklockcase伪代码如下pieceofdata}}}上面代码中的锁if如果是单机情况下的锁,在多线程服务器的情况下是没有问题的。但是在分布式环境下,单机的锁只能锁住一台服务器的物理代码块,无法防止其他机器产生的脏数据。在分布式情况下,需要将锁换成分布式锁来保证数据的一致性。3、分布式锁的实现原理依赖于一个强一致性的服务发现存储仓库。(保证数据一致性)具有高可用性的服务发现存储库。(保证服务的稳定性)这里我们使用etcd作为服务发现存储仓库。具体实现原理本次我们使用的etcd能力etcd节点维护独占能力。(同一时间只能有一个服务器有一个节点)节点事件监控能力。(节点释放/占用时可以通知observer-server)节点主动释放能力。(服务端可以主动释放所属节点)超时自动释放节点的能力。(超时后自动释放节点)代码中需要准备以下项目用于etcd长期监控。(监听etcd节点并在节点变化时做出响应)事件队列。(用于争用的etcd节点存储方法)争用锁事件。等待锁定超时事件。(流程图中没有画,争用锁事件入队时注册,持有锁时注销)持有锁超时事件。(流程图中没有画,持有锁时注册,释放锁时注销)释放锁事件。基本代码流程图普通代码流程图(用markdown画的,有点难看)st=>start:projectstartwatcher=>operation:monitoretcded=>end:waitforrequestst->watcher->edst=>start:start执行locked=>end:endwatcher=>operation:监听etcdhasEvent=>condition:eventqueueisemptypushEvent=>operation:竞争锁事件进入waitingqueuewatcherEvent=>operation:etcd节点超时事件和release事件popEvent=>operation:竞争锁事件出事件队列execute=>operation:执行加锁的代码块fight=>condition:竞争锁失败unlock=>operation:释放锁st->fightfight(no)->execute->unlock->edfight(yes)->pushEvent->watcherEvent->popEvent->fight事件详情伪代码准备一个通用的方法清除所有相关事件假设eventQueue是这个业务对应的事件队列假设fightEvent是竞争锁事件这次执行假设clear是清除超时事件方法假设holdEvent是hold锁超时事件假设waitEvent是等待锁超时事件假设unLockEvent是释放锁事件//清除所有事件-clearAlleventQueue.remove(fightEvent)clear(waitEvent)clear(holdEvent)监听etcd的两个事件//当etcd锁超时事件或etcd主动释放事件发生时//争用锁事件出事件队列fightEvent=eventQueue.pop//执行争用锁eventexecutefightEventcontentionlockevent//执行etcdcontentionlock方法if(Grabthelock){//清除所有事件并执行clearAll//设置锁超时事件并设置holdEvent}else{//如果争用锁事件是第二次入队,建议去队头,不要去队尾eventQueue.push(fightEvent)}等待锁超时事件(使用timewheeltodelayexecution)//清空所有事件,执行clearAll//throwExceptionthrownewExceptionHoldlocktimeoutevent(用时间轮延迟执行)//执行releaselockeventExecuteunLockEventreleaselockevent//Releaselockeventexecuteetcdreleaselockmethod//ClearalleventsExecuteclearAll备注以上代码可以使用有限状态机设计模式来设计业务图。项目启动时初始化分布式服务器与etcd集群交互项目。服务器A、B、C是一个分布式系统(不管哪一个是master)同时发送10个请求。假设算法分配变成这样。当锁竞争开始时,10个线程会同时与etcd竞争锁。假设请求2竞争成功,那么在第一次竞争之后,除了请求2之外的所有请求都会进入各自的事件队列,等待etcd释放锁。Notification当请求2执行完代码块后,向etcd发送锁释放请求。etcd收到锁释放请求,删除节点,触发compareAndDelete事件(锁释放事件)。三台服务器收到锁释放信息,让事件队列头请求向etcd发送请求抢锁。抢到锁后,重复4->6的行为,补充etcd也有控制时序的功能。这样就可以将每次请求抢锁的行为控制到只有一次。业务执行的顺序由etcd控制,我没试过。有兴趣的同学可以试试。基于分布式锁的原理,我之前写了一个分布式缓存锁,通过锁缓存来防止缓存崩溃。空的时候填上。感谢同学们在这里阅读我的文章。
