核心概念
- 逻辑表:水平拆分的数据库的相同逻辑和数据结构表的总称
- 真实表:在分片的数据库中真实存在的物理表。
- 数据节点:数据分片的最小单元。由数据源名称和数据表组成
- 绑定表:分片规则一致的主表和子表。
- 广播表:也叫公共表,指素有的分片数据源中都存在的表,表结构和表中的数据
在每个数据库中都完全一致。例如字典表。 - 分片键:用于分片的数据库字段,是将数据库(表)进行水平拆分的关键字段。
SQL中若没有分片字段,将会执行全路由,性能会很差。 - 分片算法:通过分片算法将数据进行分片,支持通过=、BETWEEN和IN分片。
分片算法需要由应用开发者自行实现,可实现的灵活度非常高。 - 分片策略:真正用于进行分片操作的是分片键+分片算法,也就是分片策略。在
ShardingJDBC中一般采用基于Groovy表达式的inline分片策略,通过一个包含
分片键的算法表达式来制定分片策略,如t_user_$->{u_id%8}标识根据u_id模
8,分成8张表,表名称为t_user_0到t_user_7。
ShardingJDBC的分片算法
ShardingSphere目前提供了一共五种分片策略:
NoneShardingStrategy
不分片。这种严格来说不算是一种分片策略了。只是ShardingSphere也提供了
这么一个配置。
InlineShardingStrategy
常用的分片方式
- 配置参数 inline.shardingColumn 分片键;inline.algorithmExpression
分片表达式 - 实现方式: 按照分片表达式来进行分片。
- 配置参数 inline.shardingColumn 分片键;inline.algorithmExpression
StandardShardingStrategy
只支持单分片键的标准分片策略。- 配置方式: standard.sharding-column 分片键;standard.precise-algorithm-class-name 精确分片算法类名;standard.range-algorithm-class-name 范围分片算法类名
- 实现方式:shardingColumn指定分片算法。
preciseAlgorithmClassName 指向一个实现了
io.shardingsphere.api.algorithm.sharding.standard.PreciseShardingAl
gorithm接口的java类名,提供按照 = 或者 IN 逻辑的精确分片 示例:
com.roy.shardingDemo.algorithm.MyPreciseShardingAlgorit
hm
rangeAlgorithmClassName 指向一个实现了
io.shardingsphere.api.algorithm.sharding.standard.RangeShardingAlg
orithm接口的java类名,提供按照Between 条件进行的范围分片。示例:
com.roy.shardingDemo.algorithm.MyRangeShardingAlgorithm - 说明:
其中精确分片算法是必须提供的,而范围分片算法则是可选的。
ComplexShardingStrategy
支持多分片键的复杂分片策略。- 配置参数:complex.sharding-columns 分片键(多个);
complex.algorithm-class-name 分片算法实现类。 - 实现方式:
shardingColumn指定多个分片列。
algorithmClassName指向一个实现了
org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardi
ngAlgorithm接口的java类名。提供按照多个分片列进行综合分片的算法。
示例:
com.roy.shardingDemo.algorithm.MyComplexKeysShardingAlg
orithm
- 配置参数:complex.sharding-columns 分片键(多个);
HintShardingStrategy
不需要分片键的强制分片策略。这个分片策略,简单来理解就是说,他的分片键
不再跟SQL语句相关联,而是用程序另行指定。对于一些复杂的情况,例如
select count(*) from (select userid from t_user where userid in (1,3,5,7,9))
这样的SQL语句,就没法通过SQL语句来指定一个分片键。这个时候就可以通过
程序,给他另行执行一个分片键,例如在按userid奇偶分片的策略下,可以指定
1作为分片键,然后自行指定他的分片策略。- 配置参数:hint.algorithm-class-name 分片算法实现类。
- 实现方式:
algorithmClassName指向一个实现了
org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm
接口的java类名。 示例:
com.roy.shardingDemo.algorithm.MyHintShardingAlgorithm
在这个算法类中,同样是需要分片键的。而分片键的指定是通过
HintManager.addDatabaseShardingValue方法(分库)和
HintManager.addTableShardingValue(分表)来指定。
使用时要注意,这个分片键是线程隔离的,只在当前线程有效,所以通常建
议使用之后立即关闭,或者用try资源方式打开。
而Hint分片策略并没有完全按照SQL解析树来构建分片策略,是绕开
了SQL解析的,所有对某些比较复杂的语句,Hint分片策略性能有可
能会比较好(情况太多了,无法一一分析)。
但是要注意,Hint强制路由在使用时有非常多的限制:
1 | -- 不支持UNION |
ShardingSphere的SQL使用限制
- 支持的SQL
- 不支持的SQL
- Distinct 说明
支持的SQL
不支持的SQL
分库分表带来的问题
1、分库分表,其实围绕的都是一个核心问题,就是单机数据库容量的问题。我们
要了解,在面对这个问题时,解决方案是很多的,并不止分库分表这一种。但是
ShardingSphere的这种分库分表,是希望在软件层面对硬件资源进行管理,从而便
于对数据库的横向扩展,这无疑是成本很小的一种方式。
大家想想还有哪些比较好的解决方案?
2、一般情况下,如果单机数据库容量撑不住了,应先从缓存技术着手降低对数据
库的访问压力。如果缓存使用过后,数据库访问量还是非常大,可以考虑数据库读
写分离策略。如果数据库压力依然非常大,且业务数据持续增长无法估量,最后才
考虑分库分表,单表拆分数据应控制在1000万以内。
当然,随着互联网技术的不断发展,处理海量数据的选择也越来越多。在实际进
行系统设计时,最好是用MySQL数据库只用来存储关系性较强的热点数据,而对海
量数据采取另外的一些分布式存储产品。例如PostGreSQL、VoltDB甚至HBase、
Hive、ES等这些大数据组件来存储。
3、从上一部分ShardingJDBC的分片算法中我们可以看到,由于SQL语句的功能
实在太多太全面了,所以分库分表后,对SQL语句的支持,其实是步步为艰的,稍
不小心,就会造成SQL语句不支持、业务数据混乱等很多很多问题。所以,实际使
用时,我们会建议这个分库分表,能不用就尽量不要用。
如果要使用优先在OLTP场景下使用,优先解决大量数据下的查询速度问题。而在
OLAP场景中,通常涉及到非常多复杂的SQL,分库分表的限制就会更加明显。当
然,这也是ShardingSphere以后改进的一个方向。
4、如果确定要使用分库分表,就应该在系统设计之初开始对业务数据的耦合程度
和使用情况进行考量,尽量控制业务SQL语句的使用范围,将数据库往简单的增删
改查的数据存储层方向进行弱化。并首先详细规划垂直拆分的策略,使数据层架构
清晰明了。而至于水平拆分,会给后期带来非常非常多的数据问题,所以应该谨
慎、谨慎再谨慎。一般也就在日志表、操作记录表等很少的一些边缘场景才偶尔用
用。