集群环境下防止并发的一种实现
?
近来研究定时器Quartz集群的实现原理时,发现了一种利用数据库锁的方式来实现集群环境下进行并发控制的方式。由于现在的系统多是部署在集群环境中,需要进行并发控制时,这是一种很好的实现方法,现将原理介绍如下:
?
首先,在数据库中建立一张拥有锁标识的表,建立表的SQL语句如下:
? ? ? ??CREATE TABLE TB_LOCKS
/** * Execute the given callback having optionally aquired the given lock. * This uses the non-managed transaction connection. * * @param lockName The name of the lock to aquire, for example * "TRIGGER_ACCESS". If null, then no lock is aquired, but the * lockCallback is still executed in a non-managed transaction. */ protected Object executeInNonManagedTXLock( String lockName, TransactionCallback txCallback) throws JobPersistenceException { boolean transOwner = false; Connection conn = null; try { if (lockName != null) { if (getLockHandler().requiresConnection()) { conn = getNonManagedTXConnection(); } //获得相关的锁,通过带有"for update"的select语句实现,如果这个锁被其他线程占用,执行这个操作的线程只能等待 transOwner = getLockHandler().obtainLock(conn, lockName); } if (conn == null) { conn = getNonManagedTXConnection(); } Object result = txCallback.execute(conn);//执行相关的业务逻辑操作,获得操作的结果 commitConnection(conn);//提交操作结果,释放锁 return result; } catch (JobPersistenceException e) { rollbackConnection(conn);//撤销操作结果,释放锁 throw e; } catch (RuntimeException e) { rollbackConnection(conn);//撤销操作结果,释放锁 throw new JobPersistenceException("Unexpected runtime exception: " + e.getMessage(), e); } finally { try { releaseLock(conn, lockName, transOwner); } finally { cleanupConnection(conn); } } }