利用数据库小表完成大批量数据的锁定目的,即批量任务锁。目的是为了保证操作特定任务的排他性,是一种相对乐观锁,因为它操作的不是处理数据本身,而是独立于这些数据之外,在另一张数据库表描述了操作数据的摘要,也就是关键字。
打个比方,比如现在桌上放着厚厚的20叠百元大钞(这些钱给我就爽了),现在有2个会计要对这些钞票清点,因为考虑到两个会计的点钞速度有区别,当又要达到相对相等的时间完成,他们先对20叠钞票分成20小份,并对
每份做了一次1到20的编号。现在针对点钞这个动作我们就可以用到了批量任务锁,那么锁的关键字就是【动作】+【编号】,如点钞1,点钞2等。这里点钞1和点钞2是不存在排他性要求的,关键是点钞1内部,如果会计A对
1编号钞票进行清点的时候,会计B就不能在对1编号进行操作了。这里如果用传统的悲观锁,即对没张钞票进行排他控制,效率会大大折扣。
针对上面的例子,我们可以得出两个实体,一个动作。实体2:钞票,实体2:清点任务锁;动作:清点。下面是针对三者的类图。
其中addLock方法可以是通过抛出异常或是返回结果的方式来判断是否加锁成功就随你了。下面是操作的流程图。
这样就完成最基本的任务锁控制目的。下面我们再来看看,是不是还可以做更好的优化,答案是肯定的,我们可以spring的自动代理拦截来把锁的处理隐蔽起来,也就是不要让清点任务来关心锁控制的具体操作,我们需要关心的只有这个任务我是要加这么个锁就行了,而加锁删锁操作就有拦截器来操作,这样就让点钞任务解放出来了,并且跟远的意义也是把锁解放出来,使它的功能不仅仅局限在点钞任务上。这样达到双赢,社会更加和谐。
那么我们现在来定义一个锁申明:TaskLockAnnotation,包含三个属性:任务类型、锁键值、是否抛出异常。为了达到拦截效果,我们当然还需要定义一个拦截器了,如果只需要完成简单锁要求,里面的实现也很简单,无非
是在目标方法调用前加锁,在调用后删除锁。如果加锁不成功则不执行任务。