zookeeper的watcher乐观锁实现

乐观锁简介

实现过程

乐观锁对事务的控制分为数据读取、写入校验、数据写入,JDK中最典型的乐观锁实现就是CAS。

适用场景

乐观锁适合使用在并发量不高,数据竞争不大、事务冲突较少,多读,写操作不频繁的应用场景。这是因为如果事务经常产生冲突,上层应用会不断的进行retry,进行频繁的上下文切换,这样反倒是降低了性能。另外当应用并发量高的时候,version值在频繁变化,会对数据库产生很大的写压力。

在zookeeper中的实际应用

在zookeeper中是使用version属性来实现乐观锁的写入校验。在zookeeper服务器的PreRequestProcessor处理器类中,在处理每一个数据更新(setDataRequest)请求时,会进行版本检查。

1
2
3
4
5
6
7
version = setDataRequest.getVersion();
int currentVersion = nodeRecord.stat.getVersion();
if(version != -1 && version != currentVersion)
{
throw new KeeperException.BadVersionException(path);
}
version = currentVersion + 1;

在进行一次setDataRequest请求处理时,首先进行了版本检查:zookeeper会从setDataRequest请求中获取当前请求的版本version,同时从数据记录noderecord中获取到当前服务器上该数据的最新版本currentversion。如果version为-1,那么说明客户端并不要求使用乐观锁,可以忽略版本对比;如果version不是-1,那么就对比versioncurrentversion,如果两个版本不匹配,那么就会抛出BadVersionException异常。