m)用于多个字段作为分片键的分片操作,同时获取到多个分片健的值,根据多个字段处理业务逻辑。需要在复合分片策略(ComplexShardingStrategy )下使用。
4:Hint分片算法
Hint分片算法(HintShardingAlgorithm)稍有不同,上边的算法中我们都是解析SQL 语句提取分片键,并设置分片策略进行分片。但有些时候我们并没有使用任何的分片键和分片策略,可还想将 SQL 路由到目标数据库和表,就需要通过手动干预指定SQL的目标数据库和表信息,这也叫强制路由。
注意:sharding-jdbc
并没有直接提供分片算法的实现,需要开发者根据业务自行实现。
⑦ 分片策略
上边讲分片算法的时候已经说过,分片策略是一种抽象的概念,实际分片操作的是由分片算法和分片健来完成的。
1:标准分片策略
标准分片策略适用于单分片键,此策略支持 PreciseShardingAlgorithm 和 RangeShardingAlgorithm 两个分片算法。
其中 PreciseShardingAlgorithm 是必选的,用于处理 = 和 IN 的分片。RangeShardingAlgorithm 是可选的,用于处理BETWEEN AND, >, <,>=,<= 条件分片,如果不配置RangeShardingAlgorithm,SQL中的条件等将按照全库路由处理。
2:复合分片策略
复合分片策略,同样支持对 SQL语句中的 =,>, <, >=, <=,IN和 BETWEEN AND 的分片操作。不同的是它支持多分片键,具体分配片细节完全由应用开发者实现。
3:行表达式分片策略 inline
行表达式分片策略,支持对 SQL语句中的 = 和 IN 的分片操作,但只支持单分片键。这种策略通常用于简单的分片,不需要自定义分片算法,可以直接在配置文件中接着写规则。
t_order_$->{t_order_id % 4} 代表 t_order 对其字段 t_order_id取模,拆分成4张表,而表名分别是t_order_0 到 t_order_3。
4:Hint分片策略
Hint分片策略,对应上边的Hint分片算法,通过指定分片健而非从 SQL中提取分片健的方式进行分片的策略。
⑧ 分布式主键
数据分?后,不同数据节点?成全局唯?主键是?常棘?的问题,同?个逻辑表(t_order
)内的不同真实表(t_order_n
)之间的?增键由于?法互相感知而产?重复主键。
尽管可通过设置?增主键 初始值
和 步?
的?式避免ID碰撞,但这样会使维护成本加大,乏完整性和可扩展性。如果后去需要增加分片表的数量,要逐一修改分片表的步长,运维成本非常高,所以不建议这种方式。
实现分布式主键?成器的方式很多,可以参考我之前写的9种分布式ID生成方式。
为了让上手更加简单,ApacheShardingSphere 内置了UUID
、SNOWFLAKE
两种分布式主键?成器,默认使?雪花算法(snowflake
)?成64bit的?整型数据。不仅如此它还抽离出分布式主键?成器的接口,?便我们实现?定义的?增主键?成算法。
⑨ 广播表
广播表:存在于所有的分片数据源中的表,表结构和表中的数据在每个数据库中均完全一致。一般是为字典表或者配置表 t_config
,某个表一旦被配置为广播表,只要修改某个数据库的广播表,所有数据源中广播表的数据都会跟着同步。
⑩ 绑定表
绑定表:那些分片规则一致的主表和子表。比如:t_order
订单表和 t_order_item
订单服务项目表,都是按 order_id
字段分片,因此两张表互为绑定表关系。
那绑定表存在的意义是啥呢?
通常在我们的业务中都会使用 t_order
和 t_order_item
等表进行多表联合查询,但由于分库分表以后这些表被拆分成N多个子表。如果不配置绑定表关系,会出现笛卡尔积关联查询,将产生如下四条SQL
。
SELECT * FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id
SELECT * FROM t_order_0 o JOIN t_order_item_1 i ON o.order_id=i.order_id
SELECT * FROM t_order_1 o JOIN t_order_item_0 i ON o.order_id=i.order_id
SELECT * FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id
笛卡尔积查询
而配置绑定表关系后再进行关联查询时,只要对应表分片规则一致产生的数据就会落到同一个库中,那么只需 t_order_0
和 t_order_item_0
表关联即可。
SELECT * FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id
SELECT * FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id
绑定表关系
注意:在关联查询时 t_order 它作为整个联合查询的主表。所有相关的路由计算都只使用主表的策略,t_order_item 表的分片相关的计算也会使用 t_order 的条件,所以要保证绑定表之间的分片键要完全相同。
案例准备
我们基于MyBatisPlus+ShadingJDBC
实现数据库分片、读写分离功能,准备了工程shading-jdbc
,该工程是一个SpringBoot+MyBatisPlus
实现了MySQL
增加和查询的案例,我们要将ShadingJDBC
集成进来,将它改造成具备分表分库、读写分离的案例。
准备数据库 sd1
、sd2
,在每个数据库中创建表,
表结构说明: goods 用于数据库分片。goods_0, goods_1用于表分片
创建脚本如下:
-- 数据库sd1
CREATE database `sd1` DEFAULT CHARACTER SET utf8 ;
CREATE TABLE sd1.`goods` (
`id` bigint(20) NOT NULL,
`goods_name` varchar(100) DEFAULT NULL,
`type` bigint(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
create table sd1.`goods_0` as select * from sd1.`goods` where 1=2;
create table sd1.`goods_1` as select * from sd1.`goods` where 1=2;
-- 数据库sd2
CREATE database `sd2` DEFAULT CHARACTER SET utf8 ;
create table sd2.`goods` as select * from sd1.`goods` where 1=2;
create table sd2.`goods_0` as select * from sd1.`goods` where 1=2;
create table sd2.`goods_1` as select * from sd1.`goods` where 1