动态数据源怎么与Sharding JDBC整合

这篇文章主要介绍“动态数据源怎么与Sharding JDBC整合”,在日常操作中,相信很多人在动态数据源怎么与Sharding JDBC整合问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”动态数据源怎么与Sharding JDBC整合”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

为何要保留动态数据源

原本定时任务就已经使用了动态数据源,而且一个数据源是mysql,另两个是亚马逊的db,而Sharding-JDBC并不支持亚马逊的那两个db,显然是不能去掉动态数据源的,只能想办法让两者并存。

动态数据源怎么与Sharding JDBC整合

怎样让两者并存,且互不影响

我的想法是,将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查找数据不知道查哪个表的,而且关联的表还需要使用这个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。

动态数据源怎么与Sharding JDBC整合

图中billid是我在完成数据的插入之后,查询出来的id。

表不存在时会自动创建表吗

我把官方文档从头到尾看了一个遍,但是却没有找到关于自动创建表的介绍,所以说Sharding-JDBC并没有智能到会帮我们创建表。当按分表算法计算出来的物理表不存在时,便会出现一堆的异常信息。

Table 'cayman.report_click_info_201906' doesn't exist

我目前的做法是提前创建好未来的几个月的表。缺点就是,如果有时候忘记了,整个服务都会因此而奔溃。

目前我所能想到的就是在计算表名的时候(ShardingAlgorithm的doSharding方法中),判断一下这个表是否存在,不存在则创建,但是每次都判断一次很耗性能。单库还好,多库(分库)情况下更糟糕。

插入新记录会根据分片字段路由到表吗

插入新记录时,必须保证分片字段的值不能为空,否则直接报错。因为分片字段没有值,就没有办法路由到物理表,算不出来要插入哪个表,只能放弃抛出异常了。

正常情况下不允许使用可以为null的字段进行分片。如果是使用日期类型的字段,如记录的创建时间create_datetime,作为分片(分表)字段,就不能在创建表的时候声明默认使用系统的当前时间,应该由插入数据的时候指定值,并且设置为不能为空。避免墨菲定律。

到此,关于“动态数据源怎么与Sharding JDBC整合”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

原创文章,作者:254126420,如若转载,请注明出处:https://blog.ytso.com/230327.html

(0)
上一篇 2022年1月15日
下一篇 2022年1月15日

相关推荐

发表回复

登录后才能评论