mysql分库分表中间件简书_分库分表中间件 Sharding-JDBC

1. 简介

Sharding-JDBC 是当当开源的数据库分库分表中间件,同时也支持读写分离。

Sharding-JDBC 定位为轻量级 java 框架,使用客户端直连数据库,以 jar 包形式提供服务,未使用中间层,无需额外部署,无其他依赖,DBA 也无需改变原有的运维方式,可理解为增强版的 JDBC 驱动,旧代码迁移成本几乎为零。

Sharding-JDBC 架构的核心逻辑为分片规则配置、SQL解析、SQL路由、SQL改写、SQL执行以及结果归并模块。

d5d2adeec64d?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

Sharding-JDBC 架构图

2. 客户端配置

2.1 添加 maven 依赖

com.dangdang

sharding-jdbc-core

2.0.3

2.2 分片算法

Sharding-JDBC 提供了以下 5 种分片策略,都继承至ShardingStrategy:

StandardShardingStrategy

标准分片策略(最常用)。提供对 SQL语 句中的 =, IN 和 BETWEEN AND的分片操作支持。

StandardShardingStrategy 只支持单分片键,提供PreciseShardingAlgorithm和RangeShardingAlgorithm两个分片算法。

PreciseShardingAlgorithm 是必选的,用于处理 = 和 IN 的分片。

RangeShardingAlgorithm 是可选的,用于处理 BETWEEN AND 分片,如果不配置RangeShardingAlgorithm,SQL中的 BETWEEN AND 将按照全库路由处理。

ComplexShardingStrategy

复合分片策略。提供对 SQL 语句中的 =, IN 和 BETWEEN AND 的分片操作支持。

ComplexShardingStrategy 支持多分片键,由于多分片键之间的关系复杂,因此 Sharding-JDBC 并未做过多的封装,而是直接将分片键值组合以及分片操作符交于算法接口,完全由应用开发者实现,提供最大的灵活度。

InlineShardingStrategy

Inline 表达式分片策略。使用 Groovy 的 Inline 表达式,提供对 SQL 语句中的 = 和 IN 的分片操作支持。

InlineShardingStrategy 只支持单分片键,对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的 Java 代码开发,如: tuser${user_id % 8} 表示 t_user 表按照 user_id 对 8 取模分成 8 个表,表名称为 t_user_0 到 t_user_7。

HintShardingStrategy

通过 Hint 而非 SQL 解析的方式分片的策略。

NoneShardingStrategy

不分片的策略。

2.3 自定义分片算法

Sharding-JDBC 提供了以下4种算法接口:

PreciseShardingAlgorithm

RangeShardingAlgorithm

HintShardingAlgorithm

ComplexKeysShardingAlgorithm

现在我们有个分表需求,将时间字段,如repay_date(yyyy-MM-dd)按照季度分表,例如:“table_2019q1,table_2019q2,table_2019q3,table_2019q4,...”。由于时间的比较方式通常为区间比较,于是我们可以采用StandardShardingStrategy下的分片策略。

a、PreciseShardingAlgorithm 实现:(Precise 处理 = 和 in 的路由)

public class DatePreciseShardingAlgorithm implements PreciseShardingAlgorithm {

@Override

public String doSharding(Collection availableTargetNames, PreciseShardingValue shardingValue) {

Assert.notNull(shardingValue.getValue(), "分表键不能为空");

String quarterMonth = DateShardingUtils.getYearQuarter(shardingValue.getValue());

for (String availableTarget : availableTargetNames){

if(availableTarget.endsWith(quarterMonth)){

return availableTarget;

}

}

throw new IllegalArgumentException("分表不存在,shardingValue="+quarterMonth);

}

}

b、 RangeShardingAlgorithm 实现:(Range 处理 Between And 的路由)

public class DateRangeShardingAlgorithm implements RangeShardingAlgorithm {

@Override

public Collection doSharding(Collection availableTargetNames, RangeShardingValue shardingValue) {

Range dateRange = shardingValue.getValueRange();

Assert.notNull(dateRange.lowerEndpoint(), "分表键开始时间不能为空");

Assert.notNull(dateRange.upperEndpoint(), "分表键截止时间不能为空");

Date start = DateTimeUtils.getStartOfMonth(dateRange.lowerEndpoint());

Date end = DateTimeUtils.getStartOfMonth(dateRange.upperEndpoint());

Collection tables = new HashSet();

for( Date date = start; date.compareTo(end) <= 0; date = DateUtil.addMonths(date, 1)){

String tableSuffix = DateShardingUtils.getYearQuarter(date);

for (String each : availableTargetNames) {

if (each.endsWith(tableSuffix)) {

tables.add(each);

break;

}

}

}

return tables;

}

}

如果有多个分片键的需求,如order_no,subject_no两个分片键。我们希望其按照值的后两位尾数进行分表,并且表的区间为16,如表 ”table_00,table_16,table_32,table_48,...“。假如 order_no = 1000018,其会在表 t_order_16 表中。此时就需要使用ComplexShardingStrategy策略:

ComplexKeysShardingAlgorithm 实现

public class MyComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm {

private final String ORDER_NO = "order_no";

private final String SUBJECT_NO = "subject_no";

@Override

public Collection doSharding(Collection availableTargetNames, Collection shardingValues) {

ShardingValue shardingValue = null;

if( (shardingValue = getByColumnKey(shardingValues, ORDER_NO)) != null){

return getTableByNo(availableTargetNames, shardingValue);

}else if( (shardingValue = getByColumnKey(shardingValues, SUBJECT_NO)) != null){

return getTableByNo(availableTargetNames, shardingValue);

}

}

throw new IllegalArgumentException("Unsupported shardingValues: " + JSON.toJSONString(shardingValues));

}

private ShardingValue getByColumnKey(Collection shardingValues, final String columnKey){

for(ShardingValue shardingValue : shardingValues){

if(shardingValue.getColumnName().toLowerCase().equals(columnKey)){

return shardingValue;

}

}

return null;

}

/**

* 尾数即为分表位 算法

* 截取去最后2位分表位

* @param availableTargetNames

* @param shardingValue

* @return

*/

private Collection getTableByNo(Collection availableTargetNames, ShardingValue shardingValue){

if(shardingValue instanceof ListShardingValue){

Collection noList = ((ListShardingValue) shardingValue).getValues();

Collection tables = new HashSet();

for(String no : noList){

//1、截取最后两位

int tableIndex = Integer.valueOf(StringUtils.substring(no, no.length() - TsShardingConsts.TABLE_SEQ_LENGTH));

// 分表算法,16的倍数

int actualTableSeq = tableIndex / 16 * 16 ;

//3、查找分表

for (String each : availableTargetNames) {

if (each.endsWith(actualTableSeq)) {

tables.add(each);

break;

}

}

}

return tables;

}

throw new IllegalArgumentException("ShardingValue must be instanceof ListShardingValue.");

}

}

这里需要注意的是,= 和 in 的分片值都是ListShardingValue。

2.4 分片配置

基于 xml 的配置

分片规则配置 sharding-jdbc.xml

algorithm-class="com.xxx.MyComplexKeysShardingAlgorithm" />

precise-algorithm-class="com.xxx.DatePreciseShardingAlgorithm"

range-algorithm-class="com.xxx.DateRangeShardingAlgorithm"/>

table-strategy-ref="myComplexKeysShardingAlgorithm" />

table-strategy-ref="repayDateTableStrategy" />

数据源配置 jdbc.xml

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans.xsd">

${jdbc.druid.url}

${jdbc.druid.user}

"${jdbc.druid.password}"

${jdbc.druid.filters}

${jdbc.druid.maxActive}

${jdbc.druid.initialSize}

${jdbc.druid.maxWait}

${jdbc.druid.minIdle}

${jdbc.druid.timeBetweenEvictionRunsMillis}

${jdbc.druid.minEvictableIdleTimeMillis}

${jdbc.druid.validationQuery}

${jdbc.druid.testWhileIdle}

${jdbc.druid.testOnBorrow}

${jdbc.druid.testOnReturn}

${jdbc.druid.poolPreparedStatements}

${jdbc.druid.maxOpenPreparedStatements}

基于 Spring Boot 的配置

sharding.jdbc.datasource.names=ds

sharding.jdbc.datasource.ds.type=com.alibaba.druid.pool.DruidDataSource

sharding.jdbc.datasource.ds.driver-class-name=com.mysql.jdbc.Driver

sharding.jdbc.datasource.ds.url=jdbc:mysql://localhost:3306/ds

sharding.jdbc.datasource.ds.username=root

sharding.jdbc.datasource.ds.password=123456

sharding.jdbc.config.sharding.tables.table(表名).logic-table=table

sharding.jdbc.config.sharding.tables.table.actual-data-nodes=ds.table_${[00,16,32,48,64,80,96]}

sharding.jdbc.config.sharding.tables.table.table-strategy.complex.sharding-columns=order_no,subject_no

sharding.jdbc.config.sharding.tables.table.table-strategy.complex.algorithm-class-name=com.xxx. MyComplexKeysShardingAlgorithm

sharding.jdbc.config.sharding.tables.table.logic-table=table_date

sharding.jdbc.config.sharding.tables.table.actual-data-nodes=ds.table_20${[19,20,21,22]}q${[1,2,3,4]}

sharding.jdbc.config.sharding.tables.t_order_item.table-strategy.inline.sharding-column=repay_date

sharding.jdbc.config.sharding.tables.table.table-strategy.standard.precise-algorithm-class-name=com.xxx.DatePreciseShardingAlgorithm

sharding.jdbc.config.sharding.tables.table.table-strategy.standard.range-algorithm-class-name=com.xxx. DateRangeShardingAlgorithm

至此,Sharding-JDBC 的配置已经讲完,同学们可以自己实践一下,相对来说很是很简单的。后面,我们将深入源码,了解其底层的实现机制,尽请关注!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"C语言字符串处理库函数大全-简书"是一篇在简书上的教程,介绍了C语言中常用的字符串处理库函数。 该教程详细介绍了C语言中字符串操作的相关函数,包括库函数的使用方法和示例代码。通过该教程,读者可以学习到如何使用C语言中的字符串处理函数来进行字符串的复制、连接、比较、查找、截取等操作。 在这篇教程中,读者可以了解到以下一些常见的字符串处理库函数: 1. strcpy:用于将一个字符串复制到另一个字符串中。 2. strcat:用于将一个字符串连接到另一个字符串的末尾。 3. strlen:用于计算一个字符串的长度。 4. strcmp:用于比较两个字符串的大小。 5. strchr:用于在一个字符串中查找指定字符的第一次出现位置。 6. strstr:用于在一个字符串中查找指定子串的第一次出现位置。 7. strtok:用于将一个字符串按照指定的分隔符分割成多个子串。 8. strncpy:用于将指定长度的字符串复制到目标字符串中。 9. strncmp:用于比较指定长度的两个字符串。 10. sprintf:用于将格式化的字符串输出到一个字符数组中。 这些函数在C语言中非常常用,并且对于字符串的处理非常方便。通过学习和掌握这些字符串处理库函数,可以更加高效地完成C语言程序中的字符串操作。 总之,"C语言字符串处理库函数大全-简书"这篇文章提供了丰富的字符串处理库函数以及示例代码,对于C语言开发者来说是一个很好的参考和学习资料。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值