测试ShardingSphere版本:5.2.0
下面配置中省略部分前缀,仅供参考
自动分片算法通常用在 auto-tables 中,只需配置 actualDataSources 后,其他由分片算法自行解析处理。
注意,通常自动分片算法中的分片表都是在数据源中采用类似轮训的方式进行规律分片的,如:
db_0.user_0, db_1.user_1, db_2.user_2, db_0.user_3, db_1.user_4, db_2.user_5, ...
也就是 db_{i}.user_{ni + n - 1},n为第几轮
类似 MySQL的 PATITION 里的 MOD,由ShardingSphere通过分片数和取模的分母,自动计算实际表个数。
名称 |
类型 |
描述 |
sharding-count |
int |
分片数 |
该案例实际需要 8 个数据源(也支持单数据源的场景),并且每个数据源中各有 4 个user分表,并且分表格式为 user_${0..31}
autoTables:
user:
logicTable:
actualDataSources: ds_${0..7} # 数据源inline表达式,会自动识别算法:分片键 % 8
shardingStrategy: # 分片策略
standard:
shardingColumn: id
shardingAlgorithmName: mod
shardingAlgorithms:
mod:
type: MOD
props:
sharding-count: 32 # 分片数
MOD取模通常使用与数组类型的分片,而HASH_MOD不仅适用于数值,也适用于字符串(通过hash值取模)列进行分片。该算法基本和MOD类似
名称 |
类型 |
描述 |
sharding-count |
int |
分片数 |
该案例只有一个数据源,但库内有 6个分表,并且按 order_id 的 hash值进行取模计算得到实际表。
autoTables:
t_order:
actual-data-nodes: ds.t_order_$->{0..5}
table-strategy:
standard:
sharding-algorithm-name: t-order-algorithm
sharding-column: order_id
sharding-algorithms:
t-order-algorithm:
type: HASH_MOD
props:
sharding-count: '6'
该算法会根据 (${range-upper} - ${range-lower}) / ${sharding-volume} + 2 来算出实际的分片数量,从而实现自动分片功能。
名称 |
类型 |
描述 |
range-lower |
Long |
范围下界 |
range-upper |
Long |
范围上界 |
sharding-volume |
Long |
每个分片容量 |
auto-tables:
user:
actualDataSources: db_${0..1}
shardingStrategy:
standard:
shardingAlgorithmName: volume
shardingColumn: id
sharding-algorithms:
volume:
type: VOLUME_RANGE
props:
range-lower: 0
range-upper: 20000
sharding-volume: 10000
要注意,这个算法之所以 + 2 ,实际上包含了两个隐藏表,用于储存小于 range-lower 和大于 range-upper 这两种情况的数据。
也就是说,上面的例子包含4((20000 - 0) / 10000 + 2)个分片:
db_0:
- user0: (-∞..0)
- user2: [10000..20000)
db_1:
- user1: [0..10000)
- user3: [20000..+∞)
该算法会根据自定义范围进行分片,如0~100在分片0,100~1000在分片1,1000~1500在分片2等。
名称 |
类型 |
描述 |
sharding-ranges |
String |
分片范围,多个边界可以用 , 隔开 |
auto-tables:
user:
actualDataSources: db_${0..1}
shardingStrategy:
standard:
shardingAlgorithmName: boundary
shardingColumn: id
sharding-algorithms:
boundary:
type: BOUNDARY_RANGE
props:
sharding-ranges: 10,15,100,12000,16000
在面例子中的范围字符串可以拆分为
-∞..10,
10..15,
15..100,
100..12000,
12000..16000,
16000..+∞
实际上 BOUNDARY_RANGE 有点像 VOLUME_RANGE,但 BOUNDARY_RANGE 的更灵活,容量长度可变。
日期间隔将按 时间开始边界 到 时间结束边界 之间的秒数除以 分片秒数 再加 2,从而计算出总分片数。也就是 ({datetime-upper} - {datetime-lower}) / sharding-seconds + 2 。
这里的加2也是用于补上小于 datetime-lower 和 大于 datetime-upper 的分片。
名称 |
类型 |
描述 |
datetime-lower |
String |
分片时间开始边界,格式 yyyy-MM-dd HH:mm:ss |
datetime-upper |
String |
分片时间结束边界,格式 yyyy-MM-dd HH:mm:ss |
sharding-seconds |
long |
按多少秒一个分片进行分片 |
auto-tables:
user:
actualDataSources: db_${0..1}
shardingStrategy:
standard:
shardingAlgorithmName: auto_interval
shardingColumn: create_time
auto_interval:
type: AUTO_INTERVAL
props:
datetime-lower: 2022-01-02 00:00:00
datetime-upper: 2022-01-05 00:00:00
sharding-seconds: 93600 # 一天
该案例中,会按解析为:
?, 2022-01-02 00:00:00 = 0
2022-01-02 00:00:00, 2022-01-03 00:00:00 = 1
...
2022-01-05 00:00:00, ? = 3
以下算法只适用于 standard 策略
行间分片通常用于SQL中单个 = 或 IN 操作的分键字段。
名称 |
类型 |
描述 |
algorithm-expression |
String |
分片表达式 |
allow-range-query-with-inline-sharding(非必须) |
boolean |
是否允许范围查询。注意,范围查询时将会忽略分片策略,直接使用全路由 |
tables:
position:
actualDataNodes: db_${0..1}.position # 该表达式表示 db_0.position, db_1.position
databaseStrategy:
standard:
shardingColumn: id
shardingAlgorithmName: id-mod
sharding-algorithms:
id-mod:
type: INLINE
props:
algorithm-expression: db_${id % 2} # 该表达式表示 db_0 或 db_1
该分片算法类似AUTO_INTERVAL,但比它要更加灵活,能够配置日期格式、分片后缀格式等,不过也因此配置更加复杂
属性
名称 |
类型 |
描述 |
默认值 |
datetime-pattern |
String |
自定义的日期格式,如:yyyy-MM-dd |
|
datetime-lower |
String |
分片时间开始边界 |
|
datetime-upper(按需) |
String |
分片时间结束边界 |
Now |
sharding-suffix-pattern |
String |
库表分片后缀格式(逻辑表_后缀),格式必须和 datetime-interval-unit 一致,如:yyyyMM对应MONTHS |
|
datetime-interval-amount(按需) |
int |
分片间隔 |
1 |
datetime-interval-unit(按需) |
String |
分片间隔时间单位。可选址参考ChronoUnit类 |
DAYS |
案例
tables:
position:
actualDataNodes: db_${202201..202206}.position # 该表达式表示 db_202201.position, db_202202.position...
databaseStrategy:
standard:
shardingColumn: create_time
shardingAlgorithmName: month_interval
sharding-algorithms:
type: INTERVAL
props:
datetime-pattern: yyyy-MM-dd HH:mm:ss
datetime-lower: 2022-01-01 00:00:00
datetime-interval-unit: MONTHS
sharding-suffix-pattern: yyyyMM
以下算法只适用于 complex 策略
可以使用 INLINE 进行多分片键分片。
属性
名称 |
类型 |
描述 |
sharding-columns(非必须) |
String |
分片键名称,通常在配置tables信息时指定 |
algorithm-expression |
String |
分片表达式 |
allow-range-query-with-inline-sharding(非必须) |
boolean |
是否允许范围查询。注意,范围查询时将会忽略分片策略,直接使用全路由 |
案例
tables:
position:
actualDataNodes: db_${0..1}_${0..2}.position
databaseStrategy:
complex:
shardingColumns: id, oid
shardingAlgorithmName: uoid_complex
sharding-algorithms:
uoid_complex:
type: COMPLEX_INLINE
props:
algorithm-expression: db_${id % 2}_${oid % 3} # 该表达式表示 db_0_0 到 db_1_2
实现 ComplexKeysShardingAlgorithm 接口
/**
* 基于 id 和 城市 的分片算法
*
* @author Jayin
* @email [email protected]
* @date 2022/10/11
*/
public class IdCityTableShardingAlgorithm implements ComplexKeysShardingAlgorithm {
private String tablePrefix;
private int shardingCount;
/** 配置值需要储存 */
private Properties props;
@Override
public Collection doSharding(Collection collection, ComplexKeysShardingValue complexKeysShardingValue) {
// Map的值为 Collection 类型,获取对象时需要取第一个元素
String city = (String) ((Collection) complexKeysShardingValue.getColumnNameAndShardingValuesMap().get("city")).toArray()[0];
Long id = (Long) ((Collection) complexKeysShardingValue.getColumnNameAndShardingValuesMap().get("id")).toArray()[0];
// 根据表前缀、所在地区和分片得到实际表
String table = this.tablePrefix + "_" + city + "_" + (id % shardingCount);
if (!collection.contains(table)) {
return null;
}
return Collections.singleton(table);
}
/**
* 返回配置值,因为后续对每个操作进行创建的算法对象都会获取 最初的配置信息,作为新创建对象的配置原型
* @return
*/
@Override
public Properties getProps() {
return props;
}
@Override
public String getType() {
return "ID_CITY";
}
/**
* 算法初始化,该部分可按算法需要从 props 中获取参数
* @param properties
*/
@Override
public void init(Properties properties) {
this.props = properties;
tablePrefix = StringUtils.defaultString(properties.getProperty("tablePrefix"), "position");
shardingCount = Integer.parseInt(StringUtils.defaultString(properties.getProperty("shardingCount"), "3"));
}
}
按 SPI 规范配置复合分片算法键类
在 resources/META-INF/services/org.apache.shardingsphere.sharding.spi.ShardingAlgorithm 文件中添加自定义主键类全类名
xyz.me4cxy.shardingjdbc.algorithm.IdCityTableShardingAlgorithm
使用复合分片算法
spring.shardingsphere.rules.sharding:
tables:
user:
tableStrategy:
actualDataNodes: db.user_shenzhen_${0..1}, db.user_guangzhou_${0..1} # 定义深圳、广州两个地区相关表
complex: # 使用复合算法
shardingColumns: id, city # 分片字段,也就是doSharding的数据 ComplexKeysShardingValue 来源,多个用 , 隔开
shardingAlgorithmName: id-city # 采用自定义复合算法,id、城市分片
sharding-algorithms:
id-city: # 注册算法
type: ID_CITY
props: # 添加算法所需额外配置
tablePrefix: user # 表前缀
shardingCount: 2 # 表分片数
以下算法适用于 hint 策略
该算法通过 ${value} 占位符,能够替换 HintManager 中添加值,如果添加多次值时,将会遍历每个字并执行一次 doSharding,适合用在按单个外部参数进行分片的情况。
名称 |
类型 |
描述 |
默认值 |
algorithm-expression |
String |
分片表达式,通过 ${value} 注入实际值 |
${value} |
tables:
test:
actualDataNodes: db_${0..1}.test
databaseStrategy:
hint:
shardingAlgorithmName: sys-complex-hint
sharding-algorithms:
sys-complex-hint:
type: HINT_INLINE
props:
algorithm-expression: db_${value} // 将hint注入的值代入,如 db_1
--- 使用
@Test
public void testHint() {
try (HintManager hintManager = HintManager.getInstance()) {
hintManager.addDatabaseShardingValue("test", 1L); // 指定hint注入值
System.out.println(testService.getById(3L));
}
}
用于处理使用Hint行分片的场景。对于由非SQL字段来作为分片字段的场景,而是通过其他外部方式来进行分库分表时,可使用SQL Hint灵活注入分片字段。如:根据不同端展示不同数据,而“端”由应用控制。需要通过实现 HintShardingAlgorithm 接口完成分片。
详情参考:ShardingSphere 从源码查看hint为什么失效
以下算法可适用于 standard、complex、hint
由于自定义算法通常需要注册到SPI中,但通过该算法能够配置自定义算法类,从而省去注册SPI的步骤。
注意,该算法能够将自身的 props 透传给自定义算法类的实例,所以如果自定义算法需要配置参数可通过 props 进行配置。
名称 |
类型 |
描述 |
strategy |
String |
自定义的算法类使用哪种分片策略 |
algorithmClassName |
String |
分片算法的全类名 |
tables:
position:
actualDataNodes: db_${0..1}_${0..2}.position
databaseStrategy:
complex:
shardingColumns: id, oid
shardingAlgorithmName: uoid_complex
sharding-algorithms:
id-city:
type: CLASS_BASED
props:
strategy: complex
algorithmClassName: xyz.me4cxy.shardingjdbc.algorithm.IdCityTableShardingAlgorithm
# 自定义算法的配置
tablePrefix: user # 表前缀
shardingCount: 2 # 表分片数