近来研究定时器Quartz集群的实现原理时,发现了一种利用数据库锁的方式来实现集群环境下进行并发控制的方式。由于现在的系统多是部署在集群环境中,需要进行并发控制时,这是一种很好的实现方法,现将原理介绍如下:
首先,在数据库中建立一张拥有锁标识的表,建立表的SQL语句如下:
CREATE TABLE TB_LOCKS
( LOCK_NAME VARCHAR2(40) NOT NULL,
PRIMARY KEY (LOCK_NAME)
)
表创建好之后,插入一些数据, 这些数据是根据数据库的业务逻辑操作抽象出的系统所拥有的表的类型,如"TRIGGER_ACCESS"就表示对任务触发器相关的信息进行修改删除操作时所需要获得的锁。每当要进行与某种业务相关的数据库操作时,先去这张表中查询操作相关的业务对象所需要的锁,如Quartz中需要修改触发气的状态,下次触发时间时,就需要获得"TRIGGER_ACCESS"所表示的锁。这时,执行查询这个表数据的SQL形如“select * from TB_LOCKS t where t.lock_name='TRIGGER_ACCESS' for update”,在select之后加了“for update”,就如JAVA语言中的为方法加上Symchriozed一样,起到了串形化访问修改所需数据的作用。当一个线程使用上述的SQL对表中的数据执行查询操作时,若查询结果中包含相关的行,数据库就会对这些行进行ROW LOCK。若此时又有另外一个线程使用相同的SQL对表的数据进行查询时,由于查询出的数据行已经被数据库锁住了,此时这个线程就只能等待,直到拥有这些行锁的线程完成了相关的业务操作,执行了commit动作后,数据库才会释放了相关行的锁,这个线程才能继续执行。通过这样的机制,在集群环境下,结合乐观锁的机制就可以防止一个线程对数据库数据的操作的结果被另外一个线程所覆盖,从而可以避免一些难以觉察的错误发生。当然,达到这种效果的前提是需要把Connection设置为手动提交,即autoCommit为false,下面是执行相关步骤的程序代码:
/**
* 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);
}
}
}
分享到:
相关推荐
实际应用中,可根据业务需求和技术栈选择合适方案,如结合Redis作为库存中间件,辅以分布式锁策略防止集群环境下超卖。此外,还可借助消息队列进行削峰填谷,确保系统稳定可靠。总的来说,解决商品超卖问题需要综合...
集群定义:Redis集群是一种将数据分散保存在多个Redis实例中的技术,这让Redis能够处理更多的数据。 集群优势:分布式集群能提高系统的扩展性,并提供数据冗余,防止数据丢失。 集群原理:Redis的集群通过将数据划分...
可持久化,redis提供了两种持久化方式RDB,AOF,可防止数据丢失高可用(从后期业务扩展角度考虑),redis支持集群功能,可以实现主从复制,读写分离,提供哨兵机制等等详细可参考这篇文章:内容概述对高并发业务场景...
我总结了一些包括高可用、幂等、限流、降级、断路器、事务、缓存,以及分库分表技术。这些都是在实际项目开发中非常重要的技术...断路器是一种容错机制,可以在系统遇到异常时自动切换到备用方案,避免系统的整体崩溃。
最近在工作中遇到一个问题,项目中报告查询系统负载均衡集群相关配置已经完成,两种实现方式分别是基于Ehcache和Redis的session管理策略。 大家都知道服务器资源有限的,但是客户端来的请求是无限的(不排除恶意攻击)...
Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中涉及的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等操作提供了一种...
如何实现基于HTTP协议和TCP协议的RPC调用,它们之间有何差别,分别适应何种场景。 如何实现服务的动态注册和路由,以及软负载均衡的实现。 1.1 基于TCP协议的RPC 3 1.1.1 RPC名词解释 3 1.1.2 对象的...
162.集群中有 3 台服务器,其中一个节点宕机,这个时候 zookeeper 还可以使用吗? 163.说一下 zookeeper 的通知机制? 十七、MySql 164.数据库的三范式是什么? 165.一张自增表里面总共有 7 条数据,删除了最后 2 条...
海量存储型服务器是指对服务器的存储空间要求大,如视频服务器,在线电影服务 器FTP服务器,EMAIL 服务器等则对二者都有一定的要求,视用户数的多少,用户定额空间的大小,访问的频 繁度而偏向于某一种类型。...
【集合】HashMap在并发场景下的问题和解决方案 67 多线程put后可能导致get死循环 67 多线程put的时候可能导致元素丢失 68 解决方案 68 【集合】ConcurrentHashMap的get(),put(),又是如何实现的?ConcurrentHashMap...