菜鸟笔记
提升您的技术认知

理解sharding jdbc原理,看这一篇就够了-ag真人游戏

相比于spring基于abstractroutingdatasource实现的分库分表功能,sharding jdbc在单库单表扩展到多库多表时,兼容性方面表现的更好一点。例如,spring实现的分库分表sql写法如下:

select id, name, price, publish, intro 
from book${tableindex}
where id = #{id,jdbctype=integer}

sql中的表名book需要加一个分表的后缀tableindex,也就是需要在sql注入的参数中指定插入哪个表。相比,sharding jdbc在这一块封装的更好一点。其sql中,根本不需要指定tableindex,而是根据分库分表策略自动路由。

select id, name, price, publish, intro
from book 
where id = #{id,jdbctype=integer}

sharding jdbc的这种特性,在水平扩展的时候无疑更具有吸引力。试想一下,一个项目开发一段时间后,单库单表数据量急剧上升,需要分库分表解决数据库的访问压力。而现有sql配置都是基于单库单表实现的,如果基于spring的abstractroutingdatasource实现,需要修改每一个相关表的sql,修改涉及较多地方,出错概率较大。而基于sharding jdbc实现时,sql无需修改,只需要在spring中添加sharding jdbc的相关配置即可,减少了修改面,大大简化分库分表的实现难度。

那么,sharding jdbc是如何实现这种分库分表的逻辑呢?下面我们用一段简单、易懂的代码描述sharding jdbc的原理。

通常我们在写一段访问数据库的数据时,逻辑是这样的:

    classpathxmlapplicationcontext ctx = new classpathxmlapplicationcontext("application.xml");
    datasource datasource = ctx.getbean("datasource", datasource.class);
    connection connection = datasource.getconnection();
		
    string sql = "select id, name, price, publish, intro from book where id = 111";
    preparedstatement ps = connection.preparestatement(sql);
    resultset rs = ps.executequery();
    // handle resultset...

sharding jdbc是基于jdbc协议实现的,当我们获得datasource时,这个datasource是sharding jdbc自己定义的一个springshardingdatasource类型的数据源,该数据源在返回getconnection()及preparestatement()时,分别返回shardingconnection和shardingpreparedstatement的实例对象。然后在executequery()时,shardingpreparedstatement做了这样的一件事:

  1. 根据逻辑sql,经过分库分表策略逻辑计算,获得分库分表的路由结果sqlrouteresult;
  2. sqlrouteresult中包含真实的数据源以及转换后的真正sql,利用真实的数据源去执行获得resultset;
  3. 将resultset列表封装成一个可以顺序读的resultset对象iteratorreducerresultset
class shardingpreparedstatement implements preparedstatement {
	@override
	public resultset executequery() throws sqlexception {
		list routeresults = routesql(logicsql);
		
		list resultsets = new arraylist<>(routeresults.size());
		for (sqlrouteresult routeresult : routeresults) {
			preparedstatement ps = routeresult.getdatasource().getconnection.preparestatement(routeresult.getparsedsql());
			resultset rs = ps.executequery();
			resultsets.add(rs);
		}
		
		return new iteratorreducerresultset(resultsets);
	}
        .....
}

其中,分库分表策略的sql路由过程,我们将sharding jdbc中的相关代码全部抽出来,放到一起来观看这个过程的实现:

    // 环境准备
    @suppresswarnings("resource")
    classpathxmlapplicationcontext ctx = new classpathxmlapplicationcontext("application.xml");
    springshardingdatasource datasource = ctx.getbean(springshardingdatasource.class);
    field field = springshardingdatasource.class.getsuperclass().getdeclaredfield("shardingcontext");
    field.setaccessible(true);
    shardingcontext sctx = (shardingcontext)field.get(datasource);
    shardingrule shardingrule = sctx.getshardingrule();
		
    string logicsql = "select id, name, price, publish, intro from book where id = ?";
    list
网站地图