Sharding-JDBC定位为轻量级Java框架,在Java的JDBC层提供的额外服务。可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM 框架的使用
Sharding-JDBC主要功能
1) 数据分片:分库分表、读写分离、分片策略、分布式主键
2) 分布式事务:标准化事务接口、XA强一致性事务、柔性事务
3) 数据库治理:配置动态、服务治理、数据脱敏、链路追踪
核心概念逻辑表:水平拆分的数据库的相同逻辑和数据结构表的总称
真实表:在分片的数据库中真实存在的物理表。
数据节点:数据分片的最小单元。由数据源名称和数据表组成
绑定表:分片规则一致的主表和子表。(binding-tables)
广播表:也叫公共表,指素有的分片数据源中都存在的表,表结构和表中的数据在每个数据库中都完全一致。例如字典表。(broadcast-tables)
分片键:用于分片的数据库字段,是将数据库(表)进行水平拆分的关键字段。SQL中若没有分片字段,将会执行全路由,性能会很差。
分片算法:通过分片算法将数据进行分片,支持通过=、BETWEEN和IN分片。分片算法需要由应用开发者自行实现,可实现的灵活度非常高。
分片策略:真正用于进行分片操作的是分片键+分片算法,也就是分片策略。在ShardingJDBC中一般采用基于Groovy表达式的inline分片策略,通过一个包含分片键的算法表达式来制定分片策略,如t_user_$->{u_id%8}标识根据u_id模8,分成8张表,表名称为t_user_0到t_user_7。
分片算法1) 精确分片算法PreciseShardingAlgorithm
2) 范围分片算法RangeShardingAlgorithm
3) 复合分片算法ComplexKeysShardingAlgorithm
4) Hint分片算法HintShardingAlgorithm
分片策略1) 标准分片策略StandardShardingStrateg (eq,in,between)
2) 复合分片策略ComplexShardingStrategy (多个字段联合)
3) 行表达式分片策略InlineShardingStrateg (eq)
4) Hint分片策略HintShardingStrategy (与sql无关)
5) 不分片策略NoneShardingStrategy
分片策略配置1) 数据源分片策略
2) 表分片策略
数据分片流程1) SQL解析:SQL解析分为词法解析和语法解析。先通过词法解析器将SQL拆分为一个个不可再分的单词。再使 用语法解析器对SQL进行理解,并最终提炼出解析上下文。
2) 查询优化:负责合并和优化分片条件,如OR等。
3) SQL路由:根据解析上下文匹配用户配置的分片策略,并生成路由路径。
4) SQL改写:将SQL改写为在真实数据库中可以正确执行的语句。
5) SQL执行:通过多线程执行器异步执行SQL。
6) 结果归并:将多个执行结果集归并以便于通过统一的JDBC接口输出。
数据分片SQL使用规范https://shardingsphere.apache.org/document/current/cn/features/sharding/use-norms/sql/
1) 支持路由至单数据节点时,目前MySQL数据库100%全兼容,路由至多数据节点时,全面支持DQL、DML、DDL、DCL、TCL。
2) 路由至多数据节点不支持CASE WHEN、HAVINg、UNIOn (ALL)。
3) 支持分页子查询,但其他子查询有限支持,无论嵌套多少层,只能解析第一层。
4) 由于归并的限制,子查询中包含聚合函数目前无法支持。
5) 不支持包含schema的SQL。
6) 当分片键处于运算表达式或函数中的SQL时,将采用全路由的形式获取结果。
读写分离及架构设计方案spring.shardingsphere.sharding.master-slave-rules.ds0.masterDataSourceName=m1
spring.shardingsphere.sharding.master-slave-rules.ds0.slaveDataSourceNames[0]=m2
脱敏配置四部分:数据源配置,加密器配置,脱敏表配置以及查询属性配置
数据源配置:指DataSource的配置信息
加密器配置:指使用什么加密策略进行加解密。目前ShardingSphere内置了两种加解密策略: AES/MD5
脱敏表配置:指定哪个列用于存储密文数据(cipherColumn)、哪个列用于存储明文数据(plainColumn)以及用户想使用哪个列进行SQL编写(logicColumn)
查询属性的配置:当底层数据库表里同时存储了明文数据、密文数据后,该属性开关用于决定是直接查询数据库表里的明文数据进行返回,还是查询密文数据通过Encrypt-JDBC解密后返回。
加密策略解析:
Encryptor:提供encrypt(), decrypt()两种方法对需要脱敏的数据进行加解密。
QueryAssistedEncryptor:即使是相同的数据,如两个用户的密码相同,它们在数据库里存储的脱敏数据也应当是不一样的。
jdk提供服务实现查找的一个工具类:java.util.ServiceLoader。
Java SPI 的具体约定为:当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。
分布式事务理论CAP和BASE CAP(强一致性)布鲁尔定理。对于共享数据系统,最多只能同时拥有CAP其中的两个 BASE(最终一致性)基本可用(Basically Available)、软状态( Soft State)、最终一致性( Eventual Consistency)。它的核心思想是即使无法做到强一致性(CAP 就是强一致性),但应用可以采用适合的方式达到最终一致性。
BA指的是基本业务可用性,支持分区失败;
S表示柔性状态,也就是允许短时间内不同步;
E表示最终一致性,数据最终是一致的,但是实时是不一致的。
分布式事务模式2PC和3PC 2PC模式(强一致性)两阶段提交,就是将事务的提交过程分为两个阶段来进行处理。事务的发起者称协调者,事务的执行者称参与者。
1) 阶段 1:准备阶段 协调者向所有参与者发送事务内容,询问是否可以提交事务,并等待所有参与者答复。 各参与者执行事务操作,但不提交事务,将 undo 和 redo 信息记入事务日志中。 如参与者执行成功,给协调者反馈 yes;如执行失败,给协调者反馈 no。
2) 阶段 2:提交阶段 如果协调者收到了参与者的失败消息或者超时,直接给每个参与者发送回滚(rollback)消息; 否则,发送提交(commit)消息。
2PC 方案存在的问题
1) 性能问题:所有参与者在事务提交阶段处于同步阻塞状态,占用系统资源,容易导致性能瓶颈。
2) 可靠性问题:如果协调者存在单点故障问题,如果协调者出现故障,参与者将一直处于锁定状态。
3) 数据一致性问题:在阶段 2 中,如果发生局部网络问题,一部分事务参与者收到了提交消息,另一部分事务参与者没收到提交消息,那么就导致了节点之间数据的不一致。
3PC模式(强一致性)两阶段提交的改进版本,引入超时机制,将两阶段的准备阶段拆分为 2 个阶段,插入了一个 preCommit 阶段。
1) 阶段1:canCommit 协调者向参与者发送 commit 请求,参与者如果可以提交就返回 yes 响应,否则返回 no 响应。
2) 阶段2:preCommit 协调者根据阶段 1 canCommit 参与者的反应情况执行预提交事务或中断事务操作。 参与者均反馈 yes:协调者向所有参与者发出 preCommit 请求,参与者收到 preCommit 请求后,执行事务操作,但不提交;将 undo 和 redo 信息记入事务日志 中;各参与者向协调者反馈 ack 响应或 no 响应,并等待最终指令。 任何一个参与者反馈 no或等待超时:协调者向所有参与者发出 abort 请求,无论收到协调者发出的 abort 请求,或者在等待协调者请求过程中出现超时,参与者均会中断事务。
3) 阶段3:do Commit 该阶段进行真正的事务提交,根据阶段 2 preCommit反馈的结果完成事务提交或中断操作。
事务demo @Transactional
@ShardingTransactionType(TransactionType.BASE) //LOCAL,XA,BASE
public void insertProductTransaction() {
}
properties demo
spring.shardingsphere.datasource.names=m1,m2
spring.shardingsphere.datasource.m1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m1.url=jdbc:mysql://xxxxxxxx:3316/shardingdb1
spring.shardingsphere.datasource.m1.username=root
spring.shardingsphere.datasource.m1.password=xxxxxxxx
spring.shardingsphere.datasource.m2.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.m2.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.m2.url=jdbc:mysql://xxxxxxxx:3316/shardingdb2
spring.shardingsphere.datasource.m2.username=root
spring.shardingsphere.datasource.m2.password=xxxxxxxx
#spring.shardingsphere.sharding.master-slave-rules.ds0.masterDataSourceName=m1
#spring.shardingsphere.sharding.master-slave-rules.ds0.slaveDataSourceNames[0]=m2
#spring.shardingsphere.sharding.tables.t_product.actualDataNodes=ds0.t_product
spring.shardingsphere.sharding.tables.product.actualDataNodes=m$->{1..2}.product_$->{1..2}
spring.shardingsphere.sharding.tables.product.key-generator.column=pid
spring.shardingsphere.sharding.tables.product.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.product.key-generator.props.worker.id=1
spring.shardingsphere.sharding.tables.inventory.actualDataNodes=m$->{1..2}.inventory_$->{1..2}
spring.shardingsphere.sharding.tables.inventory.key-generator.column=iid
spring.shardingsphere.sharding.tables.inventory.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.inventory.key-generator.props.worker.id=1
spring.shardingsphere.sharding.tables.product.database-strategy.inline.sharding-column=pid
spring.shardingsphere.sharding.tables.product.database-strategy.inline.algorithm-expression=m$->{pid%2+1}
spring.shardingsphere.sharding.tables.product.table-strategy.inline.sharding-column=pid
spring.shardingsphere.sharding.tables.product.table-strategy.inline.algorithm-expression=product_$->{((pid+1)%4).intdiv(2)+1}
spring.shardingsphere.sharding.tables.category.actualDataNodes=m$->{1..2}.category_$->{1..2}
spring.shardingsphere.sharding.tables.category.key-generator.column=cid
spring.shardingsphere.sharding.tables.category.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.category.key-generator.props.worker.id=1
spring.shardingsphere.sharding.broadcast-tables[0]=category
#spring.shardingsphere.sharding.binding-tables[0]=product,inventory
spring.shardingsphere.props.sql.show=true
standard.....
complex.....
hint.....
Sharding-JDBC 源码流程
Sharding-Proxy
下载: https://shardingsphere.apache.org/document/current/cn/downloads/
- conf/server.yaml、conf/config-sharding.yaml (config-encrypt.yaml config-master_slave.yaml config-shadow.yaml logback.xml)
- If you want to connect to MySQL, you should manually copy MySQL driver to lib directory.
- ./bin/start.sh 3316
- tail -f logs/stdout.log
- mysql -h0.0.0.0 -P3316 -usharding -psharding
- show databases;
- use sharding_db
- show tables;
配置:ConfigurationPropertyKey.java



