2025年数据库垂直切分迁移实战

数据库垂直切分迁移实战原文链接 https github com Elin Zhou develop doc blob master E6 95 B0 E6 8D AE E5 BA 93 E5 9E 82 E7 9B B4 E5 88 87 E5 88 86 E8 BF 81 E7 A7 BB md 背景 原来的业务所有数据库都在一个实例上 配置为 8C64G 1TB 由于业务快速增长 在业务高峰期时

大家好,我是讯享网,很高兴认识大家。

原文链接:https://github.com/Elin-Zhou/develop-doc/blob/master/%E6%95%B0%E6%8D%AE%E5%BA%93%E5%9E%82%E7%9B%B4%E5%88%87%E5%88%86%E8%BF%81%E7%A7%BB.md

背景

原来的业务所有数据库都在一个实例上,配置为8C64G 1TB。由于业务快速增长,在业务高峰期时,数据库QPS大约12k+,频繁出现数据库CPU使用率达到100%的情况。

问题分析

短期问题可以通过升级数据库配置解决,但是单机配置有上限,且约往后越不划算,单机的瓶颈会越来越明显,所以需要考虑对数据库进行拆分。

水平拆分OR垂直拆分

一般情况下,考虑数据拆分时,分为水平拆分和垂直拆分两个方向。根据经验,水平拆分适合数据量非常大的单表,而垂直拆分适合多个数据表按业务情况拆分到不同的数据库实例中,所以此处选择垂直拆分。

实现

流程

整体流程参照下图,大致分为五个步骤

数据同步

此处需要DBA配置,创建一个新的数据库实例,并且把需要迁移到新库中的业务表结构与数据进行同步,需要保证旧表与新表的数据是准实时的。一般来说两表的同步时延很短,最多不过几秒钟。

上线/下线路由代码

由于业务逻辑比较简单,此处不引入第三方中间件,通过Sping自带的AbstractRoutingDataSource来实现数据的路由功能,具体实现下文会详细描述。

因为切换的操作是单向的,所以路由功能只需要在操作时使用,如果确定业务正常,则可以下线动态路由功能,改为静态配置选择具体使用的数据源。

路由开关

由于线上机器较多,路由代码上线后不能直接开启,需要有一个开关统一来开启,保证所有机器路由的一致性。

关键点

数据源路由

上文提到,动态路由功能可以通过使用Spring提供的动态数据源来实现,即继承AbstractRoutingDataSource类,实现其determineCurrentLookupKey方法,简单看一下这个方法的签名及注释

/ * Determine the current lookup key. This will typically be * implemented to check a thread-bound transaction context. * <p>Allows for arbitrary keys. The returned key needs * to match the stored lookup key type, as resolved by the * {@link #resolveSpecifiedLookupKey} method. */ protected abstract Object determineCurrentLookupKey(); 
讯享网

在AbstractRoutingDataSource中有一个Map类型的成员变量targetDataSources,其key可以进行自定义,value即为对应的数据源,需要在初始化实例的是往这个map中写入所有动态的数据源,每次有请求数据源的请求时,均会调用determineCurrentLookupKey,需要方法实现中根据情况返回key来选择对应的数据源。

讯享网private Map<Object, Object> targetDataSources; 

有了这个接口,我们需要在其中根据当前数据的请求情况,来判断是走旧库还是新库。而在原来使用数据源的地方,需要修改为这个数据源。

在MyBatis中,可以根据SqlSessionTemplate来隔离两个数据源,前面提到,只需要将一部分业务从原来的数据库中移到新的数据库,那么其中一部分表的访问路径是不变的。所以根据业务情况,将一个SqlSessionTemplate拆成两个。

我们将原来的业务库称为basic库,把新的业务库称为new库,那么SqlSessionTemplate也需要两个,一个是basicSqlSessionTemplate,固定请求原来的数据源;另一个是newSqlSessionTemplate,其请求的数据源需要动态切换的。 下文我们只讨论需要切换的数据源,两个SqlSessionTemplate的拆分由读者自行实现,本文不再赘述。

例如项目中使用MyBatis作为ORM,所以在配置SqlSessionTemplate中是这么配置的(本文中的所有代码与配置均为实例,只展示大致的逻辑,不一定是真实可用的)

<!--原数据库的数据源配置 --> <bean name="basicDataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close"> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </bean> <!--需要迁移的业务走这个SqlSessionTemplate --> <bean id="newSqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg> <bean class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="basicDataSource"/> <property name="mapperLocations" value="classpath:mybatis/new/*.xml"/> <property name="configLocation" value="classpath:mybatis/sqlMapConfig.xml"/> </bean> </constructor-arg> </bean> 

改造后的数据源配置大致是如下的情况其中com.xxelin.datasource.RoutingDataSource类为我们自己实现的动态数据源类,后文会提供代码。

讯享网<!--原数据库的数据源配置 --> <bean name="basicDataSource"
小讯
上一篇 2025-03-06 20:09
下一篇 2025-04-10 22:04

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/68865.html