我们知道,当前的应用都离不开数据库,随着数据库中的数据越来越多,单表突破性能上限记录时,如MySQL单表上线估计在近千万条内,当记录数继续增长时,从性能考虑,则需要进行拆分处理。而拆分分为横向拆分和纵向拆分。一般来说,采用横向拆分较多,这样的表结构是一致的,只是不同的数据存储在不同的数据库表中。其中横向拆分也分为分库和分表。
在Java语言下的框架中,有众多的开源框架,其中关于分库分表的框架,可以选择Apache ShardingSphere
官网地址为: https://shardingsphere.apache.org/index_zh.html
ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由 JDBC、Proxy 和 Sidecar(规划中)这 3 款既能够独立部署,又支持混合部署配合使用的产品组成。 它们均提供标准化的基于数据库作为存储节点的增量功能,可适用于如 Java 同构、异构语言、云原生等各种多样化的应用场景
ShardingSphere定位为关系型数据库中间件,旨在充分合理地在分布式的场景下利用关系型数据库的计算和存储能力,而并非实现一个全新的关系型数据库。 它与NoSQL和NewSQL是并存而非互斥的关系。NoSQL和NewSQL作为新技术探索的前沿,放眼未来,拥抱变化,是非常值得推荐的。反之,也可以用另一种思路看待问题,放眼未来,关注不变的东西,进而抓住事物本质。 关系型数据库当今依然占有巨大市场,是各个公司核心业务的基石,未来也难于撼动,我们目前阶段更加关注在原有基础上的增量,而非颠覆
定位为轻量级Java框架,在Java的JDBC层提供的额外服务。 它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架。
定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。 目前提供 MySQL 和 PostgreSQL(兼容 openGauss 等基于 PostgreSQL 的数据库)版本,它可以使用任何兼容 MySQL/PostgreSQL 协议的访问客户端(如:MySQL Command Client, MySQL Workbench, Navicat 等)操作数据,对 DBA 更加友好。
定位为 Kubernetes 的云原生数据库代理,以 Sidecar 的形式代理所有对数据库的访问。 通过无中心、零侵入的方案提供与数据库交互的啮合层,即 Database Mesh
,又可称数据库网格。
Database Mesh 的关注重点在于如何将分布式的数据访问应用与数据库有机串联起来,它更加关注的是交互,是将杂乱无章的应用与数据库之间的交互进行有效地梳理。 使用 Database Mesh,访问数据库的应用和数据库终将形成一个巨大的网格体系,应用和数据库只需在网格体系中对号入座即可,它们都是被啮合层所治理的对象。
Sharding-JDBC | Sharding-Proxy | Sharding-Sidecar | |
---|---|---|---|
数据库 | 任意 | MySQL | MySQL |
连接消耗数 | 高 | 低 | 高 |
异构语言 | 仅Java | 任意 | 任意 |
性能 | 损耗低 | 损耗略高 | 损耗低 |
无中心化 | 是 | 否 | 是 |
静态入口 | 无 | 有 | 无 |
ShardingSphere-JDBC 采用无中心化架构,与应用程序共享资源,适用于 Java 开发的高性能的轻量级 OLTP 应用; ShardingSphere-Proxy 提供静态入口以及异构语言的支持,独立于应用程序部署,适用于 OLAP 应用以及对分片数据库进行管理和运维的场景。
Apache ShardingSphere 是多接入端共同组成的生态圈。 通过混合使用 ShardingSphere-JDBC 和 ShardingSphere-Proxy,并采用同一注册中心统一配置分片策略,能够灵活的搭建适用于各种场景的应用系统,使得架构师更加自由地调整适合于当前业务的最佳系统架构。
<dependency>
<groupId>org.apache.shardingspheregroupId>
<artifactId>shardingsphereartifactId>
<version>5.1.0version>
dependency>
数据源:6个数据源,两个集群,分别为1主2从;
主1:master0;从1:master0salve0;从2:master0slave1
主2:master1;从1:master1slave0;从2:master1slave1
作为demo演示,将表进行分库和分表;每个库里有两张表:mc_member0和mc_member1;
分库规则:gender=1(男)时 gender%2 -> master1库; gender=2(女)时 gender%2 -> master0库;
分表规则:id偶数时,id%2->mc_member0表;id为奇数时,id%2->mc_member1表;
注意事项:对逻辑表配置分片策略时,数据库分片策略设置逻辑数据源,不使用物理库名;表分片策略内,使用物理表名;
配置读写分离:master-slave-rules下的rule逻辑名可以自定义如 ms1和ds1等。
sharding:
jdbc:
datasource:
#数据源名称,多数据源以逗号分隔
names: master0,master0salve0,master0slave1,master1,master1slave0,master1slave1
master0:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/mcspcsharding0?useUnicode=true&character_set_server=utf8mb4&useSSL=false&serverTimezone=GMT%2B8
username: ***
password: ***
master0salve0:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/mcspcsharding0s0?useUnicode=true&character_set_server=utf8mb4&useSSL=false&serverTimezone=GMT%2B8
username: ***
password: ***
master0slave1:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/mcspcsharding0s1?useUnicode=true&character_set_server=utf8mb4&useSSL=false&serverTimezone=GMT%2B8
username: ***
password: ***
master1:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/mcspcsharding1?useUnicode=true&character_set_server=utf8mb4&useSSL=false&serverTimezone=GMT%2B8
username: ***
password: ***
master1slave0:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/mcspcsharding1s0?useUnicode=true&character_set_server=utf8mb4&useSSL=false&serverTimezone=GMT%2B8
username: ***
password: ***
master1slave1:
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://localhost:3306/mcspcsharding1s1?useUnicode=true&character_set_server=utf8mb4&useSSL=false&serverTimezone=GMT%2B8
username: ***
password: ***
#分库策略,缺省表示使用默认分库策略,以下的分片策略只能选其一
config:
sharding:
tables:
mc_member:
#由数据源名 + 表名组成,以小数点分隔。多个表以逗号分隔,支持inline表达式。缺省表示使用已知数据源与逻辑表名称生成数据节点。
#用于广播表(即每个库中都需要一个同样的表用于关联查询,多为字典表)或只分库不分表且所有库的表结构完全一致的情况
actual-nodes: mcspcsharding$->{0..1}.mc_member$->{0..1}
#分库规则配置
database-strategy:
inline:
#分片列名称
sharding-column: gender
#分片算法行表达式,需符合groovy语法
algorithm-expression: master$->{gender % 2}
#分表规则配置
table-strategy:
inline:
#分片列名称
sharding-column: id
#分片算法行表达式,需符合groovy语法
algorithm-expression: mc_member$->{id % 2}
#绑定表规则列表,多个时逗号隔开
binding-tables: mc_member
#广播表规则列表,多个时逗号隔开
broadcast-tables: mc_master
master-slave-rules:
ms0:
master-data-source-name: master0
slave-data-source-names: master0salve0,master0slave1
ms1:
master-data-source-name: master1
slave-data-source-names: master1slave0,master1slave1
#是否开启SQL显示,默认值: false
props:
sql:
show: true
wget https://downloads.apache.org/shardingsphere/5.1.0/apache-shardingsphere-5.1.0-shardingsphere-proxy-bin.tar.gz
tar zxvf apache-shardingsphere-5.1.0-shardingsphere-proxy-bin.tar.gz
cd apache-shardingsphere-5.1.0-shardingsphere-proxy-bin/conf/
配置文件简介
config-master_slave.yaml 用来配置读写分离
config-sharding.yaml 用来配置分库分表(也可以在该文件中配置读写分离+分库分表)
config-shadow.yaml 用来配置影子库
config-encrypt.yaml 用来配置数据加密
server.yaml Sharding-Proxy的一些基础配置,比如:账号、密码、注册中心等
logback.xml 日志的配置
修改server.yaml:
rules:
- !AUTHORITY
users:
- ***@:***# 用于登录计算节点的用户名,授权主机和密码的组合。格式:@:,hostname 为 % 或空字符串表示不限制授权主机
provider:
type: NATIVE # 存储节点数据授权的权限提供者类型
schemaName: sharding_db # 逻辑数据源名称
dataSources: # 数据源配置,可配置多个
ds_0: # 与 ShardingSphere-JDBC 配置不同,无需配置数据库连接池
url: jdbc:mysql://127.0.0.1:3306/demo_ds_0?useSSL=false #数据库 URL 连接
username: *** # 数据库用户名
password: *** # 数据库密码
connectionTimeoutMilliseconds: 30000 # 连接超时毫秒数
idleTimeoutMilliseconds: 60000 # 空闲连接回收超时毫秒数
maxLifetimeMilliseconds: 1800000 # 连接最大存活时间毫秒数
maxPoolSize: 50 # 最大连接数
minPoolSize: 1 # 最小连接数
ds_1:
url: jdbc:mysql://127.0.0.1:3306/demo_ds_1?useSSL=false
username: ***
password: ***
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules: # 与 ShardingSphere-JDBC 配置一致
- !SHARDING
tables:
t_order:
actualDataNodes: ds_${0..1}.t_order_${0..1}
tableStrategy:
standard:
shardingColumn: order_id
shardingAlgorithmName: t_order_inline
keyGenerateStrategy:
column: order_id
keyGeneratorName: snowflake
t_order_item:
actualDataNodes: ds_${0..1}.t_order_item_${0..1}
tableStrategy:
standard:
shardingColumn: order_id
shardingAlgorithmName: t_order_item_inline
keyGenerateStrategy:
column: order_item_id
keyGeneratorName: snowflake
bindingTables:
- t_order,t_order_item
defaultDatabaseStrategy:
standard:
shardingColumn: user_id
shardingAlgorithmName: database_inline
defaultTableStrategy:
none:
shardingAlgorithms:
database_inline:
type: INLINE
props:
algorithm-expression: ds_${user_id % 2}
t_order_inline:
type: INLINE
props:
algorithm-expression: t_order_${order_id % 2}
t_order_item_inline:
type: INLINE
props:
algorithm-expression: t_order_item_${order_id % 2}
keyGenerators:
snowflake:
type: SNOWFLAKE
props:
worker-id: 123
mysql-connector-java-5.1.47.jar
或``mysql-connector-java-8.0.11.jar,并将其放入 %SHARDINGSPHERE_PROXY_HOME%/lib
目录启动:
./apache-shardingsphere-5.1.0-shardingsphere-proxy-bin/bin/start.sh 3388
查看日志:
tail -f /root/shardingSphere-proxy/shardingsphere-5.1.0/logs/stdout.log
测试:
在sharding_db数据库中创建t_order和t_order_item表
CREATE TABLE t_order (
ORDER_id BIGINT(20) NOT NULL AUTO_INCREMENT,
user_id INT(11) NOT NULL,
STATUS VARCHAR(50) COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (order_id)
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
CREATE TABLE t_order_item(
order_item_id BIGINT(20) NOT NULL,
order_id BIGINT(20) NOT NULL,
user_id INT(11) NOT NULL,
content VARCHAR(255) COLLATE utf8_bin DEFAULT NULL,
STATUS VARCHAR(50) COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (order_item_id)
)ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
创建完成后:
测试插入:
INSERT INTO t_order (user_id, STATUS) VALUES(1,1);
INSERT INTO t_order (user_id, STATUS) VALUES(2,1);
INSERT INTO t_order (user_id, STATUS) VALUES(2,2);
后续可优化为:
ShardingSphere-Proxy + ShardingSphere-ui + zookeeper 可以实现服务治理以及页面化配置