分库分表
说明
Zebra 微服务框架引入了 ShardingSphere 的 Sharding-JDBC 组件来支持分库分表功能。
Sharding-JDBC 相关说明请参考官方文档。
样例
参考 TODO
开发
依赖引入
引入如下依赖
<dependency>
<groupId>com.guosen</groupId>
<artifactId>zebra-database</artifactId>
<version>${zebra.version}</version>
</dependency>
注:将 ${zebra.version} 替换为使用的 Zebra 版本
配置
配置样例
zebra.database.url[0]=jdbc:sqlserver://ip:port;database=dbName01
zebra.database.username[0]=sa
zebra.database.pwd[0]=password
zebra.database.dataSourceName[0]=ds0
zebra.database.url[1]=jdbc:sqlserver://ip:port;database= dbName02
zebra.database.username[1]=sa
zebra.database.pwd[1]=password
zebra.database.dataSourceName[1]=ds1
zebra.database.shardingcfg.shardDs01.datasource.names=ds0,ds1
zebra.database.shardingcfg.shardDs01.basePackage=com.guosen.zebra.demo.sharding.dao
zebra.database.shardingcfg.shardDs01.sharding.tables.t_credit.actual-data-nodes=ds$->{0..1}.t_credit_$->{2019..2039}0$->{1..9},ds$->{0..1}.t_credit_$->{2019..2039}$->{10..12}
zebra.database.shardingcfg.shardDs01.sharding.tables.t_credit.table-strategy.inline.sharding-column=m_month
zebra.database.shardingcfg.shardDs01.sharding.tables.t_credit.table-strategy.inline.algorithm-expression=t_credit_$->{m_month}
zebra.database.shardingcfg.shardDs01.sharding.tables.t_credit.database-strategy.inline.sharding-column=fund_id
zebra.database.shardingcfg.shardDs01.sharding.tables.t_credit.database-strategy.inline.algorithm-expression=ds$->{fund_id % 2}
zebra.database.shardingcfg.shardDs01.props.sql.show=true
如上图,上述配置项配置了一个逻辑表 t_credit 的分库分表规则。
三个关键的配置项说明如下:
zebra.database.shardingcfg.shardDs01.datasource.names
组成分库分表的原始数据源名称,一个到多个,以逗号分隔。
比如上述配置
zebra.database.shardingcfg.shardDs01.datasource.names=ds0,ds1
ds0 对应数据源配置项 zebra.database.dataSourceName[0]=ds0 的值。
ds1 对应数据源配置项 zebra.database.dataSourceName[1]=ds1 的值。
t_credit.database-strategy相关的配置项
配置了分库规则
t_credit.database-strategy.inline.algorithm-expression=ds$->{fund_id%2}表示根据 SQL 中的 fund_id 字段对 2 取模来确定该 SQL 要路由到哪个数据源对应的数据库执行。
比如 SQL
select * from t_credit where m_month = 201908 and fund_id = 8888
那么最后分库 SQL 会变为(仍和上面分表 SQL 一致)
select * from t_credit_201908 where m_month = 201908 and fund_id = 8888
路由到的数据源为ds$->{8888%2} = ds0,该 SQL 会被路由到 ds0 对应的数据库中执行。
t_credit.table-strategy 相关的配置项
配置了分表规则
tcredit.table-strategy.inline.algorithm-expression=t_credit$->{m_month} 表示根据SQL中 m_month 进行分表。
比如 SQL
select * from t_credit where m_month = 201908 and fund_id = 8888
那么最后分表 SQL 会变为
select * from t_credit_201908 where m_month = 201908 and fund_id = 8888
配置说明
和 Sharding-JDBC 基本保持一致,但是配置前缀修改为 zebra.database.shardingcfg.${分库分表数据源名称}
关键配置项
配置项 | 说明 |
---|---|
datasources.name | 组成分库分表的原始数据源名称,一个到多个,以逗号分隔。 原始数据源名称为 zebra.database.dataSourceName[k]=dsName 对应的值 |
basePackage | 分库分表对应 MyBatis 的 basePackage,此为 Zebra 定制配置项 |
tables.tableName.actual-data-nodes | 由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持 inline 表达式。缺省表示使用已知数据源与逻辑表名称生成数据节点。用于广播表(即每个库中都需要一个同样的表用于关联查询,多为字典表)或只分库不分表且所有库的表结构完全一致的情况 |
props.sql.show | 表示是否开启分库分表SQL打印。 true : 开启; false : 不开启(默认值) 开启时,会打印出逻辑SQL和分库分表之后实际的SQL。一般用于开发阶段的问题定位。生产环境不要打开此开关 |
其他配置项 | 参考 ShardingSphere SpringBoot 配置,将前缀“spring.shardingsphere”修改为 zebra 的前缀“zebra.database.shardingcfg.${分库分表数据源名称}” 即可。 |
代码
代码开发和已有 Zebra 数据库开发方式保持一致。但是相关业务 SQL 必须带上分库分表字段,如果没有带,则 Sharding-JDBC 会扫描配置的所有表,速度很可能就非常慢。
相关限制
下面仅列出 Zebra 开发验证时发现的问题。
SQLServer 的限制
如果使用的数据为 SQLServer,则应该注意如下问题。
分页
Sharding-JDBC 对 SQLServer 的分页支持不完整,官网宣称可以 2 种分页方式:TOP + ROWNUMBER和 OFFSET FETCH。经验证,2 种都有不同程度的 bug。 分页查询当前实际只支持 OFFSET FETCH 方式,必须同时带上包含了分表分库字段的 where 条件,若不带分库分表字段条件,则返回的数据可能会比实际的多。
已经在 GitHub 上面提了 issue
字段不能为 SQLServer 保留字
当字段名称和保留字一样时,Sharding-JDBC 解析业务 SQL 会报错,但仅仅只是打印错误信息,不终止后续步骤,分库分表会失效,变成在逻辑表的所有物理表上执行 SQL。所以使用分库分表的表,一定不能使用保留字作为字段名称(其实不使用分库分表也应该遵循这个规则)。