Java|乐观锁和悲观锁在zookeeper中的应用

【Java|乐观锁和悲观锁在zookeeper中的应用】一、概念介绍
1、悲观锁,又称为悲观并发控制(Pessimistic Concurrency Control,PCC),是数据库中一种非常典型且非常严格的并发控制策略。悲观锁具有强烈的独占和排他特性,能够有效地避免不同事务对同一数据并发更新而造成的数据一致性问题。悲观锁的实现原理中,如果一个事务(假定事务A)正在对数据进行处理,那么在整个处理过程中,都会将数据处于锁定状态,在这期间,其他事务将无法对这个数据进行更新操作,直到事务A完成对该数据的处理,释放了对应的锁之后,其他事务才能够重新竞争来对数据进行更新操作。也就是说,对于一份独立的数据,系统只分配了一把唯一的钥匙,谁获得了这把钥匙,谁就有权利更新这份数据。一般我们认为,在实际生产应用中,悲观锁策略适合解决那些对于数据更新竞争十分激烈的场景,在这类场景中,通常采用简单粗暴的悲观锁机制来解决并发控制的问题。


2、乐观锁,又称为乐观并发控制(Optimistic Concurrency Control,OCC),也是一种常见的并发控制策略。相对于悲观锁而言,乐观锁机制显得更加宽松与友好。悲观锁假定不同事务之间的处理一定会出现互相干扰,从而需要在一个事务从头到尾的过程中都对数据进行加锁处理。而乐观锁则不会对多个进程产生影响。因此在事务处理的绝大部分时间里不需要进行加锁处理。乐观锁机制中,在更新请求提交前,每个事务都会首先检查当前事务读取数据之后,是否会有其他事务对此数据进行了修改。如果其他事务有更新,则正在提交的数据必须要回滚。乐观锁通常适用于使用在数据并发不大,事务冲突较少的应用场景中。
乐观锁有三个阶段,分别是数据读取、写入校验和数据写入,其中写入校验是整个乐观锁控制的关键所在。在写入校验阶段,事务会检查数据在读取阶段后是否有其他事务对数据进行过更新,以确保数据更新的一致性。


3、CAS理论
对于v值,每次更新前都会对比其值是否是预期值a,只有符合预期,才会将v原子化地更新到值b,其中是否符合预期便是乐观锁中的“写入校验”阶段。


而在zookeeper中,是通过version版本号来控制实现乐观锁中的“写入校验”机制。在zookeeper之内,在处理器中,是用如下方法实现:

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,那么就对比version和currentversion,如果两个版本不匹配,那么就会抛出BadVersionException异常。


    推荐阅读