这篇文章主要介绍“动态数据源怎么与Sharding JDBC整合”,在日常操作中,相信很多人在动态数据源怎么与Sharding JDBC整合问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”动态数据源怎么与Sharding JDBC整合”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
原本定时任务就已经使用了动态数据源,而且一个数据源是mysql,另两个是亚马逊的db,而Sharding-JDBC并不支持亚马逊的那两个db,显然是不能去掉动态数据源的,只能想办法让两者并存。
我的想法是,将mysql数据源配置给Sharding-JDBC数据源,让Sharding-JDBC管理,而动态数据源则管理Sharding-JDBC数据源。配置并不需要改动什么。事务管理者依然是使用动态数据源配置。
动态数据源的配置如果还不了解,可以看下我之前写的这篇:Spring Boot项目多数据源配置
只需要将原本动态数据源的配置修改为如下,将原本mysql数据源的位置替换为Sharding-JDBC数据源即可。事务的配置不需要改。
/**
* 动态数据源: 通过AOP在不同数据源之间动态切换
*
* @return
*/
@Primary
@Bean(name = "dynamicDataSource")
public DataSource dynamicDataSource(@Qualifier("shardingDataSource") DataSource shardingDataSource,
@Qualifier("athena-database") DataSource athenaDatabase) {
DynamicDataSource dynamicDataSource = new DynamicDataSource();
// 默认数据源,当没有使用@DataSource注解时使用,
// 而使用了@DataSource注解如果没有设置beanName也要Aop自己配置使用默认的bean
dynamicDataSource.setDefaultTargetDataSource(shardingDataSource);
// 配置多数据源
// key -> bean
Map<Object, Object> dsMap = new HashMap();
dsMap.put(DataSourceContextHolder.getDefaultDataSource(), shardingDataSource);
dsMap.put("athenaDatabase", athenaDatabase);
dynamicDataSource.setTargetDataSources(dsMap);
return dynamicDataSource;
}
/**
* 配置@Transactional事物注解
* 使用动态数据源
*
* @return
*/
@Bean("dynamicDataSourceTransactionManager")
public PlatformTransactionManager transactionManager(@Qualifier("dynamicDataSource") DataSource dynamicDataSource) {
return new DataSourceTransactionManager(dynamicDataSource);
}
将mysql数据源配置给Sharding-JDBC数据源。
@Bean(name = "shardingDataSource") public DataSource dataSource(@Qualifier("mysql-database") DataSource mysqlDatabase) throws SQLException { Map<String, DataSource> dataSourceMap = new HashMap<>(); dataSourceMap.put("ds01", mysqlDatabase); return ShardingDataSourceConfig.getShardingDataSource(dataSourceMap, "ds01");}
Sharding-JDBC数据源配置看上篇:优化优化再优化之后,还是要分表,今日主角Sharding-JDBC
如果不是配置多个数据源且多个数据源之间没有统一的管理者,那么才需要为每个数据源配置一个事务管理者。
看下DataSourceTransactionManager的源码你就明白了。DataSourceTransactionManager是通过数据源获取连接Connection的,事务的提交与回滚调用的是Connection的commit与rollback方法。所以,使用动态数据源,事务管理者获取到的就是目标数据源返回的连接Connection。
现在只是将Sharding-JDBC数据源配置给动态数据源,而mysql数据源则配置给Sharding-JDBC数据源。Sharding-JDBC数据源跟动态数据源一样,在getConnection被调用时动态选择目标数据源,然后调用所选数据源的getConnection方法。这是一种设计模式,外界并不需要关心具体是如何获取到正确的数据源的Connection的。
我在配置中指定了自增主键使用雪花算法生成的id。因为分表后不能再使用数据库的自增主键,否则根据id查找数据不知道查哪个表的,而且关联的表还需要使用这个id进行分表。
在配置表的路由规则的时候,除了配置表的分片策略,如果需要修改主键的生成,还需要给表的路由配置添加主键生成器,如下配置。官方提供uuid和雪花算法两种分布式主键生成方法。
// 配置分布式id生成算法,必须使用雪花算法,否则report_click_info表无法与之关联Properties properties = new Properties();properties.setProperty("worker.id", "10");result.setKeyGeneratorConfig(new KeyGeneratorConfiguration("SNOWFLAKE", "id", properties));
为何使用雪花算法:
1.雪花算法生成的id是增长的,也就是有序的。在插入时不需要调整索引B+树。
2.原本数据库中的id是整型,BIGINT(20),所以使用雪花算法不需要修改表的结构,也不需要添加额外的列。
3.使用雪花算法可以推算出日期,对于关联表可以使用这个特点实现分表。
验证结果如下图,不出意料,确实在插入数据的使用Sharding-JDBC改写了sql,加入id字段,并使用雪花算法生成一个id。
图中billid是我在完成数据的插入之后,查询出来的id。
我把官方文档从头到尾看了一个遍,但是却没有找到关于自动创建表的介绍,所以说Sharding-JDBC并没有智能到会帮我们创建表。当按分表算法计算出来的物理表不存在时,便会出现一堆的异常信息。
Table 'cayman.report_click_info_201906' doesn't exist
我目前的做法是提前创建好未来的几个月的表。缺点就是,如果有时候忘记了,整个服务都会因此而奔溃。
目前我所能想到的就是在计算表名的时候(ShardingAlgorithm的doSharding方法中),判断一下这个表是否存在,不存在则创建,但是每次都判断一次很耗性能。单库还好,多库(分库)情况下更糟糕。
插入新记录时,必须保证分片字段的值不能为空,否则直接报错。因为分片字段没有值,就没有办法路由到物理表,算不出来要插入哪个表,只能放弃抛出异常了。
正常情况下不允许使用可以为null的字段进行分片。如果是使用日期类型的字段,如记录的创建时间create_datetime,作为分片(分表)字段,就不能在创建表的时候声明默认使用系统的当前时间,应该由插入数据的时候指定值,并且设置为不能为空。避免墨菲定律。
到此,关于“动态数据源怎么与Sharding JDBC整合”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。