ShardingSphere实战及剖析

简介

ShardingSphere 是一套开源的分布式数据库解决方案组成的生态圈,它由 JDBC、Proxy 和 Sidecar(规划中)这 3 款既能够独立部署,又支持混合部署配合使用的产品组成。 它们均提供标准化的数据水平扩展、分布式事务和分布式治理等功能,可适用于如 Java 同构、异构语言、云原生等各种多样化的应用场景。
ShardingSphere 已于2020年4月16日成为 Apache 软件基金会的顶级项目。

主要功能

数据分片分布式事务数据库治理
分库分表标准化事务接口配置动态化
读写分离XA强一致事务编排治理
分片策略定制化柔性事务数据脱敏
无中心化分布式主键 可视化链路追踪

核心三件套

 Sharding-JDBCSharding-ProxySharding-Sidecar
数据库任意MySQLMySQL
连接消耗数
异构语言JAVA 任意任意
性能损耗低损耗略高损耗低
无中心化
静态入口

Sharding-JDBC

客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可以理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。

  • 适用于任何基于JDBC的ORM框架:JPA、Hibernate、Mybatis、Spring JDBC Template或直接使用JDBC。
  • 支持任务第三方的数据库连接池:DBCP、C3P0、BoneCP、Druid、HikariCP等。
  • 支持任意实现JDBC规范的数据库。支持MySQL、Oracle、SQLServer、PostgreSQL等数据库。

Sharding-Proxy

透明化的数据库代理端,兼容所有MySQL/PostgreSQL协议的客户端。

  • 向应用程序完全透明,可直接当做MySQL服务使用。
  • 适用于任何兼容MySQL/PostgreSQL协议的客户端。

核心概念

逻辑表

水平拆分的数据库(表)的相同逻辑和数据结构表的总称。例如:订单表拆分成t_order_0到t_order_9,他们的逻辑表名为t_order。

真实表

在分片的数据库中真实存在的物理表,即t_order_0到t_order_9。

数据节点

数据分片的最小单元。由数据源名称和数据表组成,例如:database_0.t_order_0。

绑定表

分片规则一致的主表和从表。例如:t_order和t_order_item,均按照order_id分片,则此两表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔集,关联查询效率大大提升。

广播表

指所有的分片数据源都存在的表,表结构和数据完全一致。适用于数据量不大且需要与海量数据的表进行关联查询的场景,例如字典表。

实战配置

SpringBoot+Mybatis+Sharding-JDBC

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>${shardingsphere.version}</version>
</dependency>

分库分表配置

# 配置ds0 和ds1两个数据源
spring.shardingsphere.datasource.names=ds0,ds1

#ds0 配置
spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://localhost:3306/shop_ds_0?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=root
#ds1 配置
spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://localhost:3306/shop_ds_1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=root

# 分库策略 根据id取模确定数据进哪个数据库
spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds$->{user_id % 2}
spring.shardingsphere.sharding.binding-tables=t_order,t_order_item
spring.shardingsphere.sharding.broadcast-tables=t_address

# 具体分表策略
# 节点 ds0.t_order_0,ds0.t_order_1,ds1.t_order_0,ds1.t_order_1
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds$->{0..1}.t_order_$->{0..1}
# 分表字段id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
# 分表策略 根据id取模,确定数据最终落在那个表中
spring.shardingsphere.sharding.tables.t_order.table
-strategy.inline.algorithm-expression = t_order_$->{order_id % 2}
# 使用SNOWFLAKE算法生成主键
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123

# 节点 ds0.t_order_item_0,ds0.t_order_item_1,ds1.t_order_item_0,ds1.t_order_item_1
spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=ds$->{0..1}.t_order_item_$->{0..1}
# 分表字段id
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.sharding-column=order_id
# 分表策略 根据id取模,确定数据最终落在那个表中
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.algorithm-expression=t_order_item_$->{order_id % 2}
# 使用SNOWFLAKE算法生成主键
spring.shardingsphere.sharding.tables.t_order_item.key-generator.column=order_item_id
spring.shardingsphere.sharding.tables.t_order_item.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order_item.key-generator.props.worker.id=123

读写分离配置

#shardingsphere 读写分离,master-slave,可以一主多从
spring.shardingsphere.datasource.names=ds-master,ds-slave0
#主库
spring.shardingsphere.datasource.ds-master.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-master.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-master.jdbc-url=jdbc:mysql://localhost:3306/shop_ds_master?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-master.username=root
spring.shardingsphere.datasource.ds-master.password=root
#从库0
spring.shardingsphere.datasource.ds-slave0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-slave0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-slave0.jdbc-url=jdbc:mysql://localhost:3306/shop_ds_slave?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-slave0.username=root
spring.shardingsphere.datasource.ds-slave0.password=root
#从库1
#spring.shardingsphere.datasource.ds-slave1.type=com.zaxxer.hikari.HikariDataSource
#spring.shardingsphere.datasource.ds-slave1.driver-class-name=com.mysql.jdbc.Driver
#spring.shardingsphere.datasource.ds-slave1.jdbc-url=jdbc:mysql://localhost:3306/shop_ds_slave1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
#spring.shardingsphere.datasource.ds-slave1.username=root
#spring.shardingsphere.datasource.ds-slave1.password=root

#读写分离主从规则设置,当有2个以上从库时,从库读采用轮询的负载均衡机制
spring.shardingsphere.masterslave.load-balance-algorithm-type=round_robin
spring.shardingsphere.masterslave.name=ms
spring.shardingsphere.masterslave.master-data-source-name=ds-master
spring.shardingsphere.masterslave.slave-data-source-names=ds-slave0

读写分离+分库分表配置

#shardingsphere 读写分离+分库分表,master-slave-sharding,可以一主多从
spring.shardingsphere.datasource.names=ds-master0,ds-slave0,ds-master1,ds-slave1
#主库0
spring.shardingsphere.datasource.ds-master0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-master0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-master0.jdbc-url=jdbc:mysql://localhost:3306/shop_ds_master?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-master0.username=root
spring.shardingsphere.datasource.ds-master0.password=root
#从库0
spring.shardingsphere.datasource.ds-slave0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-slave0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-slave0.jdbc-url=jdbc:mysql://localhost:3306/shop_ds_slave?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-slave0.username=root
spring.shardingsphere.datasource.ds-slave0.password=root
#主库1
spring.shardingsphere.datasource.ds-master1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-master1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-master1.jdbc-url=jdbc:mysql://localhost:3306/shop_ds_master1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-master1.username=root
spring.shardingsphere.datasource.ds-master1.password=root
#从库1
spring.shardingsphere.datasource.ds-slave1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds-slave1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-slave1.jdbc-url=jdbc:mysql://localhost:3306/shop_ds_slave1?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8
spring.shardingsphere.datasource.ds-slave1.username=root
spring.shardingsphere.datasource.ds-slave1.password=root

# 分库策略 根据id取模确定数据进哪个数据库
spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=user_id
spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds_$->{user_id % 2}
spring.shardingsphere.sharding.binding-tables=t_order,t_order_item
spring.shardingsphere.sharding.broadcast-tables=t_address

#分表策略
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds_$->{0..1}.t_order_$->{0..1}
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 2}
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123
spring.shardingsphere.sharding.tables.t_order_item.actual-data-nodes=ds_$->{0..1}.t_order_item_$->{0..1}
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.sharding-column=order_id
spring.shardingsphere.sharding.tables.t_order_item.table-strategy.inline.algorithm-expression=t_order_item_$->{order_id % 2}
spring.shardingsphere.sharding.tables.t_order_item.key-generator.column=order_item_id
spring.shardingsphere.sharding.tables.t_order_item.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order_item.key-generator.props.worker.id=123

#读写分离数据源0
spring.shardingsphere.sharding.master-slave-rules.ds_0.master-data-source-name=ds-master0
spring.shardingsphere.sharding.master-slave-rules.ds_0.slave-data-source-names=ds-slave0
#读写分离主从规则设置,当有2个以上从库时,从库读采用轮询的负载均衡机制
spring.shardingsphere.sharding.master-slave-rules.ds_0.load-balance-algorithm-type=ROUND_ROBIN

#读写分离数据源1
spring.shardingsphere.sharding.master-slave-rules.ds_1.master-data-source-name=ds-master1
spring.shardingsphere.sharding.master-slave-rules.ds_1.slave-data-source-names=ds-slave1
#读写分离主从规则设置,当有2个以上从库时,从库读采用轮询的负载均衡机制
spring.shardingsphere.sharding.master-slave-rules.ds_1.load-balance-algorithm-type=ROUND_ROBIN

实现原理

源码模块

模块名称

作用

sharding-core

sharding内核模块;定义了核心api,SQL解析,SQL重写,SQL路由,spi,引擎等等核心功能

sharding-distribution

部署、运维相关zip包中的代码

sharding-integration-test

整合测试

sharding-jdbc

app-分库分表jdbc增强

sharding-opentracing

应用性能监控

sharding-orchestration

数据库编排治理

sharding-proxy

服务端代理分库分表模块

sharding-spring

与spring集成

sharding-sql-test

SQL测试用例

sharding-transaction

分布式事务

数据分片执行过程

https://note.youdao.com/yws/public/resource/b1ab33c6129db4e88980c121bd34bc33/xmlnote/97646E9EA7EA4BD79ECD9DD9EBDC06FC/6083

解析引擎

解析过程分为词法解析和语法解析。 词法解析器用于将SQL拆解为不可再分的原子符号,称为Token。并根据不同数据库方言所提供的字典,将其归类为关键字,表达式,字面量和操作符。 再使用语法解析器将SQL转换为抽象语法树。

路由引擎

内置的分片策略大致可分为尾数取模、哈希、范围、标签、时间等。 由用户方配置的分片策略则更加灵活,可以根据使用方需求定制复合分片策略。

https://note.youdao.com/yws/public/resource/b1ab33c6129db4e88980c121bd34bc33/xmlnote/075FF6BA4AE64D759858FC46EA919E94/6084

SQL改写

在分表的场景中,需要将分表配置中的逻辑表名称改写为路由之后所获取的真实表名称。

https://note.youdao.com/yws/public/resource/b1ab33c6129db4e88980c121bd34bc33/xmlnote/12ACE5AD5C284E7E9345368579AD3E5A/6081

执行引擎

https://note.youdao.com/yws/public/resource/b1ab33c6129db4e88980c121bd34bc33/xmlnote/80705EAB0CFF429CB846627CF3200549/6085

结果归并

将从各个数据节点获取的多数据结果集,组合成为一个结果集并正确的返回至请求客户端,称为结果归并。

https://note.youdao.com/yws/public/resource/b1ab33c6129db4e88980c121bd34bc33/xmlnote/0ED446194A554CD2A2AF571D429E90A0/6082

三个核心类

核心类基本都是在jdbc的基础上封装了一层,扩展了路由、分片等逻辑。

  • ShardingDataSource:增加了ShardingRule路由规则(包括分布式主键ShardingKeyGenerator),ShardingRuntimeContext上下文。
  • ShardingConnection:增加了datasource数据源map,runtimeContext上下文,TransactiontType事务类型。
  • ShardingStatement:主要实现了executeQuery()等查询方法,包括主要方法:清理准备环境clearPrevious()、准备分片shard(sql)、初始化查询器initStatementExecutor()、执行查询&归并引擎并归并结果MergeEngineFactory.newInstance()、清理工作准备环境clearPrevious()。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值