首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > PowerDesigner >

HRegion.doMiniBatchUpdate步骤解析

2012-06-28 
HRegion.doMiniBatchUpdate方法解析?-- doMiniBatchPut(BatchOperationInProgress)?实例化一个WALEdit??如

HRegion.doMiniBatchUpdate方法解析

?

-- doMiniBatchPut(BatchOperationInProgress)

?

实例化一个WALEdit

?

?

如果CoprocessorHost不为空,对每一个Put操作调用CoprocessorHost的prePut方法,如果该方法返回true,设置这次Put操作的返回状态为

?

SUCCESS。(为什么要这样做?CoprocessorHost是干什么用的?调用prePut又是为何,源代码中说是为了防止死锁,为何这样做就能防止死锁?如果不这样做就会有死锁发生?)

?

?

一开始设置变量firstIndex和lastIndexExclusive,二者都为此次batchOperation的nextIndexToProcess。

?

?

只要lastIndexExclusive小于此次批次操作的总数量,做下面的循环,该循环的主要功能是尽可能多地得到操作某一行的行锁。

++++++++++++++++++++++++++++++++++++++++++++++++++++

?

得到下次要做处理的Put(通过batchOp.operations[lastIndexExclusive]得到),同时提取该Put的familyMap信息。

?

如果该次Put操作的状态已经执行过了(不一定是已经执行过,只要该次操作的结果code不等于OperationStatusCode.NOT_RUN),

?

lastIndexExclusive递增,退出该次操作,处理下一个Put操作。

?

检查familyMap是否合法,如果不合法,将该次Put操作的结果code设置为OperationStatusCode.BAD_FAMILY,同时递增lastIndexExclusive,退

?

出该次操作,处理下一个操作。

?

下面做该步骤的主要任务:得到该行的锁。

要获得锁需要判断客户端是否提供了lockId:

====================================================

a) 如果客户端提供了lockId,但是该行并没有被锁住,说明客户端提供了一个非法的锁,抛出一个IOException。

?

b) 如果客户端没有提供lockId,尝试调用internalObtainRowLock获得该行的锁,该方法保证一个row只能有一个锁存在。HRegion在关于行锁方

?

面有三个数据结构,分别是lockedRows,该变量是一个ConcurrentHashMap<HashedBytes, CountDownLatch>,以HashedBytes为key,该key即是

?

row,value为CountDownLatch;另外一个变量是lockIds,该变量也是一个ConcurrentHashMap<Integer, HashedBytes>,该变量的key为Integer

?

,即一把锁id,value为该锁对应的row;第三个变量是AtomicInteger类型的lockIdGenerator,当生成新的lockId时,循环incrementAndGet方

?

法直到得到一个没有被使用的锁id。使用ConcurrentHashMap.putIfAbsent方法保证了map操作的原子性。

====================================================

?

++++++++++++++++++++++++++++++++++++++++++++++++++++

?

?

此刻,我们尽可能地将游标(lastIndexExclusive)移到了该批次的尾端,firstIndex到lastIndexExclusive之间的Put操作是我们下面要做的

?

操作。下面记这些Put操作为集合PS。

?

?

对集合PS中的每一个put操作,调用updateKVTimestamps更新family的timestamp。

?

?

尝试获得updatesLock的读锁。

?

?

对集合PS中的每一个put操作,调用addFamilyMapToWALEdit,将该put的familyMap信息保存到WALEdit。

?

?

调用HLog的append方法,将WALEdit保存,这一步即是写入操作日志。

?

?

对集合PS中的每一个put操作,调用applyFamilyMapToMemstore,将该put的familyMap信息保存的memstore。此时,数据在内存中就做了添加或

?

更新。如果该

?

?

如果coprocessorHost不为空,对集合PS中的每一个put操作,调用coprocessorHost的postPut做善后处理。

?

?

设置标识变量success为true,该变量代表本批次操作是否完全成功(当然,并不是每一个put操作都成功,如果某个put的familyMap不合法,该

?

put的操作结果code为BAD_FAMILY)。

?

?

finally的善后工作

++++++++++++++++++++++++++++++++++++++++++++++++++++

?

如果获得了读锁,就解锁。

?

?

集合PS中的每一个put操作的行锁(这些行锁在最开始的循环中得到,并放入了List<Integer>类型的acquiredLocks变量中)。

?

?

如果success为false,即在处理某一个put时出错抛出了异常,需要对PS集合中操作结果是NOT_RUN的操作做处理,将这些操作结果code设置为

?

FAILURE。

?

++++++++++++++++++++++++++++++++++++++++++++++++++++

?

?

-- 能学到什么?

?

1) 合理使用ConcurrentHashMap.putIfAbsent,在不使用synchronized的情况下保证操作的原子性,提高性能。

?

2) 对大块的逻辑操作,一定要使用finally做最终的善后处理,处理诸如解锁,移除一些变量,将某些错误的操作记录下来。

?

?

?

热点排行