业务场景:
在数据量非常大的应用中,通常采用主库和读库的模式来实现读写分离,降低数据库的访问压力。
解决方案:
我们使用买家库作为主库,主库又叫买家库,按照买家id作为划分分库分表的维度。所有写操作,按照买家id进行的读操作走该库。
读库又叫卖家库,按照卖家id来作为分库分表的维度。按照卖家id进行读操作走该库。
主库(买家库)数据更新以后通过同步机制同步到读库(卖家库)。
我们在执行一条数据写入或者读出的时候都需要选择,走买家或者卖家库。so,我们需要对业务逻辑做一个数据路由。
数据路由的实现。
我们实现了一个SqlMapBaseDao的基类,该类实现了基本的CRDU的接口实心,如下:
//插入操作
protected Object executeInsert(String statementName, Object parameterObject, DBRoute dr){ }; //修改操作 protected int executeUpdate(String statementName, Object parameterObject, DBRoute dr) throws DAOException{ }; //查询操作 protected List executeQueryForList(String statementName, Object parameterObject, DBRoute dr) throws DAOException{ };
该类实现的CRDU比起spring提供的数据库操作支持类的各个函数多了一个参数DBRoute。这个参数就是用来指定需要路由到哪个具体库的信息。
说具体了就是这个DBRoute告诉你到底是写入到买家库还是卖家库!当然,更多的库备份也是可以的,只要你设定号DBRoute,下面就拆开DBRoute和SqlMapBaseDao来看看内部的工作机制。
先来看一下类结构图好了!
我们先解析一下DBRoute的结构
DBRoute提供了一个Strategy来设定路由的模式,可以设定BY_XID,BY_USER,BY_ITEM三种方式,对应着也就有三种对应状态,如果你设定使用xid来判断,那么你就需要设定对应的xid的值。这些都会在DBRoutingConfig里面用到。我们来看DBRouteConfig里面的代码。
DBRouteConfig提供了routingDB函数的几个重载版本,可以通过DBRoute,sql语句,或组合两个条件查询返回对应的数据库的名字。注意,DBRouteConfig里面的allNodeNameList只存了数据库的名字,使用xml的配置文件配置。这样DBRouteConfig提供了从DBRoute或者sql语句转换成对应应该走得数据库的名字。
SqlMapBaseDaoSupport里面有一个数据源的map,按照数据库名字,数据源对象的方式存放,我们根据DBRouteConfig得到的数据库名字,在这里可以转换成数据源对象,实际上已经是SqlMapClientTemplate对象了。