
📚 本文收录于「bksczm」的系列专栏
一、ShardingSphere 定位
ShardingSphere-Proxy 对应用层伪装成一个 MySQL 服务(默认端口 3307)。应用把它当成一个普通 MySQL 连接,SQL 全部发给它,由它负责:
- 读写分离路由:写走主库、读走从库;
- 分片路由:按分片算法把 SQL 路由到真实的库/表;
- 结果归并、分布式主键生成、分布式事务协调。
它的角色和之前讲的"网关服务器"一致:一个无状态的 SQL 路由/负载均衡层。
安装参考:Shardingsphere安装-CSDN博客

二、读写分离
2.1 读写分离的思想
- 主库(Master):处理所有写操作(INSERT/UPDATE/DELETE/DDL);
- 从库(Slave):处理读操作(SELECT),多个从库分担读压力;
- 中间通过 binlog relaylog 主从复制保证数据同步。
ShardingSphere 负责把 SQL 按类型分流,应用无需关心主从地址。
2.2 配置文件 config-readwrite-splitting.yaml(逐行注释)
# ─────────────────────────────────────────────────────
# 逻辑数据库名:应用连接 Proxy 后 USE 的库名,由 Proxy 虚拟出来
# ─────────────────────────────────────────────────────
databaseName: readwrite_splitting_db
# ─────────────────────────────────────────────────────
# dataSources:声明所有「真实 MySQL 实例」的连接池
# ─────────────────────────────────────────────────────
dataSources:
write_ds: # 自定义数据源名(主库/写库)
url: jdbc:mysql://127.0.0.1:3306/test_db? # JDBC 地址:协议://IP:端口/库名
characterEncoding=utf8& # 连接字符编码
serverTimezone=Asia/Shanghai& # 时区
allowPublicKeyRetrieval=true& # 8.0 允许获取公钥
useSSL=false # 内网关闭 SSL
username: root # 连接用户名
password: 'xxxxxxxxxxxxxx' # 密码(含 @、. 等特殊字符必须加引号)
connectionTimeoutMilliseconds: 30000 # 建立连接超时(毫秒)
idleTimeoutMilliseconds: 60000 # 空闲连接回收时间(毫秒)
maxLifetimeMilliseconds: 1800000 # 连接最大存活时间(30 分钟)
maxPoolSize: 50 # 连接池最大连接数
minPoolSize: 1 # 连接池最小空闲连接数
read_ds_0: # 从库 1(容器映射端口 53307)
url: jdbc:mysql://127.0.0.1:53307/test_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: backup
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
read_ds_1: # 从库 2(容器映射端口 53308,不能与从库1重复)
url: jdbc:mysql://127.0.0.1:53308/test_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: backup
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
# ─────────────────────────────────────────────────────
# rules:规则区(读写分离、分片、加密等可叠加)
# ─────────────────────────────────────────────────────
rules:
– !READWRITE_SPLITTING # 声明:读写分离规则
dataSources:
readwrite_ds: # 逻辑读写分离数据源名(对外引用)
staticStrategy: # 静态策略:主从角色固定
writeDataSourceName: write_ds # 写请求 → write_ds
readDataSourceNames: # 读请求 → 从下面列表中选
– read_ds_0
– read_ds_1
loadBalancerName: random # 引用负载均衡算法
loadBalancers: # 负载均衡算法定义区
random: # 算法名(与上面对应)
type: RANDOM
# 类型:RANDOM / ROUND_ROBIN / WEIGHT
⚠️ YAML 格式红线:全部用空格缩进,禁止 Tab;每层 2 个空格;冒号后面必须有一个空格。内容一样却报错时,十有八九是格式问题,建议手敲一遍。
JDBC URL 各段含义
jdbc:mysql://127.0.0.1:3306/test_db?characterEncoding=utf8&serverTimezone=…
└──┬──┘ └──┬──┘ └────┬────┘ └─┬─┘ └─┬──┘ └──────────┬───────────────┘
协议 子协议 主机IP 端口 库名 连接参数
- jdbc:mysql:使用 JDBC 协议连接 MySQL;
- 127.0.0.1:本机回环地址(不是公网 IP),跨主机连接时填真实 IP;
- ? 后面是连接参数(字符集、时区、SSL 等)。
2.3 负载均衡算法
| ROUND_ROBIN | 轮询,读请求依次分给各从库 | 机器性能相同,最常用 |
| RANDOM | 随机 | 配置简单 |
| WEIGHT | 按权重比例分发 | 从库性能不同 |
WEIGHT 配置示例:
loadBalancers:
weight:
type: WEIGHT
props:
read_ds_0: 2.0
read_ds_1: 1.0
表示总体上按 2:1 分配(不是"先给 0 发两条、再给 1 发一条")。
2.4 连接与测试
# 连接 ShardingSphere-Proxy(注意是 3307,不是 3306;-h 小写)
mysql -h 127.0.0.1 -P 3307 -uroot -p
另开一个终端监控日志:
tail -f logs/stdout.log
验证:
- 执行 INSERT,日志显示路由到 write_ds(主库);
- 执行 SELECT,日志显示路由到某个 read_ds(从库)。
2.5 主从延迟问题
异步复制下,刚写入主库的数据可能还没同步到从库,此时读从库会读到旧数据。处理策略:
- 写后立即读的强一致场景(支付后跳订单页)强制走主库;
- 开启半同步复制缩短延迟;
- 监控从库延迟,延迟过大时摘除该从库。
三、分库分表核心概念
ShardingSphere 把分库分表统称为分片(Sharding)。
3.1 垂直分库
一个库里表太多、业务太杂,按业务关联性拆库,部署到不同服务器:
- 例:用户库 db_user、订单库 db_order、商品库 db_goods;
- 效果:既缓解压力,又真正扩容(不同服务器)。
3.2 垂直分表
一个表字段太多、存在大字段(如商品描述 TEXT),把不常用大字段拆成 1:1 扩展表:
- t_goods(id, name, price) 与 t_goods_desc(goods_id, description);
- 通过主键 goods_id 对应;
- 效果:主表行变小、B+ 树更矮、单页能放更多行;但仍在同一服务器,不扩容。
3.3 水平分表
表行数太多,按分片键 + 算法把数据行拆到多张结构相同的表:
- 例:user_id % 2 = 0 进 goods_0,= 1 进 goods_1;
- 仍在同一服务器,不扩容,解决单表行数过多。
3.4 水平分库
把数据行拆到不同服务器上的同名库:
- 例:goods_0 在机器 A,goods_1 在机器 B;
- 效果:性能与容量双提升。
3.5 四种方式对比
| 垂直分库 | 按业务拆库 | 是 | 业务耦合、整体压力 |
| 垂直分表 | 拆字段 | 否 | 大字段、行过大 |
| 水平分表 | 拆数据行 | 否 | 单表行数过多 |
| 水平分库 | 拆数据行到不同机器 | 是 | 单表大 + 容量 |
分库基本针对服务器层面;分表常在单服务器内操作。
四、垂直分库配置
config-sharding.yaml:
databaseName: sharding_db
dataSources:
server_user:
url: jdbc:mysql://127.0.0.1:3306/test_db_id?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: '@Czm388512369.'
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
server_order:
url: jdbc:mysql://192.168.80.138:53311/test_db_desc?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
username: backup
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules:
– !SHARDING
tables:
user: # 逻辑表名称(自定义)
actualDataNodes: server_user.t_user # 数据源名.真实表名
order:
actualDataNodes: server_order.t_order
- actualDataNodes:数据源名.真实表名,指定逻辑表数据落在哪个真实节点;
- 连接逻辑库 USE sharding_db 后,对 user 的 SQL 路由到用户库,对 order 的 SQL 路由到订单库。
只在读写分离文件里配多个写库也能"间接"实现垂直分库,参考附录!!!,但 SHARDING 规则提供了自动路由、分片算法、绑定表、主键生成等完整能力,生产应在分片规则中做(或两条规则叠加,见第九章)。
五、水平分片配置(包括bind、broadcast、keygenerator)
假设:先按 user_id 分库(2 个库),再按 goods_id 分表(每个库 2 张表),共 4 个真实节点。
5.1 建真实表
— 实例0(test_db_id0)
CREATE DATABASE IF NOT EXISTS test_db_id0;
USE test_db_id0;
CREATE TABLE IF NOT EXISTS goods_id_gd0 (id INT PRIMARY KEY, user_id INT NOT NULL, goods_id VARCHAR(20) NOT NULL);
CREATE TABLE IF NOT EXISTS goods_id_gd1 (id INT PRIMARY KEY, user_id INT NOT NULL, goods_id VARCHAR(20) NOT NULL);
— 实例1(test_db_id1)
CREATE DATABASE IF NOT EXISTS test_db_id1;
USE test_db_id1;
CREATE TABLE IF NOT EXISTS goods_id_gd0 (id INT PRIMARY KEY, user_id INT NOT NULL, goods_id VARCHAR(20) NOT NULL);
CREATE TABLE IF NOT EXISTS goods_id_gd1 (id INT PRIMARY KEY, user_id INT NOT NULL, goods_id VARCHAR(20) NOT NULL);
5.2 完整配置与逐行注释
databaseName: sharding_db # 逻辑库名
dataSources:
server_user0: # 物理数据源 0
url: jdbc:mysql://127.0.0.1:3306/test_db_id0?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: '@Czm388512369.'
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
server_user1: # 物理数据源 1
url: jdbc:mysql://192.168.80.138:53311/test_db_id1?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
username: backup
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules:
– !SHARDING
tables:
t_goods: # 逻辑表名(应用 SQL 里写的表名)
# 行表达式,展开后是 4 个真实节点:
# server_user0.goods_id_gd0 / server_user0.goods_id_gd1
# server_user1.goods_id_gd0 / server_user1.goods_id_gd1
actualDataNodes: server_user${0..1}.goods_id_gd${0..1}
databaseStrategy: # 分库策略(选库)
standard: # 标准分片:单分片键,支持 =、IN、范围
shardingColumn: user_id # 分片键
shardingAlgorithmName: alg_mod # 引用算法
tableStrategy: # 分表策略(选表)
standard:
shardingColumn: goods_id
shardingAlgorithmName: alg_hash_mod
keyGenerateStrategy: # 分布式主键
column: id
keyGeneratorName: snowflake
bindingTables: # 绑定表
– t_goods,t_goods_item
broadcastTables: # 广播表
– t_dict
shardingAlgorithms: # 分片算法定义
alg_mod:
type: MOD # 取模(分片键须为数值)
props:
sharding-count: 2 # 分片值 % 2
alg_hash_mod:
type: HASH_MOD # 先哈希再取模(字符串也能用)
props:
sharding-count: 2
alg_inline:
type: INLINE # 行表达式
props:
algorithm-expression: server_user${user_id % 2}
keyGenerators:
snowflake:
type: SNOWFLAKE
props:
worker-id: 1
5.3 行表达式
- ${0..1}:连续枚举;${[a,b,c]}:离散枚举;
- server_user${0..1}.goods_id_gd${0..1} 是两侧枚举的笛卡尔组合,得到 4 个节点。
5.4 分片策略
| STANDARD | 单分片键,处理精确(=、IN)和范围(>、<、BETWEEN) |
| COMPLEX | 多分片键 |
| HINT | 不依赖 SQL,代码手动指定路由 |
| NONE | 不强制 |
5.5 分片算法
| MOD | 分片值直接取模(数值) |
| HASH_MOD | 先哈希再取模(字符串可用) |
| INLINE | Groovy 表达式,最灵活 |
| INTERVAL | 按时间区间(按月/天) |
| BOUNDARY_RANGE / VOLUME_RANGE | 按范围/容量 |
| CLASS | 自定义算法类 |
六、绑定表(bind)完整场景
6.1 构造场景
t_order 和 t_order_item 都按 order_id 分 2 个库(偶数→ds0,奇数→ds1)。
这样子做也能够确保有关数据在同一个库中,避免跨库事务
ds0:
— t_order
order_id=100 user_id=1 amount=100
order_id=102 user_id=2 amount=200
— t_order_item
item_id=1 order_id=100 goods='手机'
item_id=2 order_id=100 goods='耳机'
item_id=3 order_id=102 goods='电脑'
ds1:
— t_order
order_id=101 user_id=3 amount=50
order_id=103 user_id=4 amount=80
— t_order_item
item_id=4 order_id=101 goods='书'
item_id=5 order_id=103 goods='键盘'
全量关联查询:
SELECT o.order_id, i.goods
FROM t_order o
JOIN t_order_item i ON o.order_id = i.order_id;
6.2 没有配置 bindingTables(笛卡尔积路由)
Proxy 不知道两表分片规则相同,把路由集合做笛卡尔积:t_order 集合 {ds0,ds1} × t_order_item 集合 {ds0,ds1} = 4 条 SQL:
| ① | ds0.t_order × ds0.t_order_item | 有效本地 JOIN |
| ② | ds1.t_order × ds1.t_order_item | 有效本地 JOIN |
| ③ | ds0 × ds1 | 跨库 JOIN,MySQL 无法执行,数据拉到内存归并 |
| ④ | ds1 × ds0 | 跨库 JOIN,MySQL 无法执行,数据拉到内存归并 |
带 WHERE o.order_id=100 时:t_order 能确定到 ds0,但 t_order_item 未被声明绑定,仍向 ds0、ds1 都发,产生 2 条 SQL(ds1 白跑)。
6.3 配置绑定表后
bindingTables:
– t_order,t_order_item
Proxy 知道同一 order_id 的订单和明细必在同一节点:
- 全量 JOIN:只下发 2 条(ds0、ds1 各本地 JOIN);
- 带 order_id=100:精确路由到 ds0,只下发 1 条。
6.4 对比
| 未绑定 | 4 条(2×2) | 2 条 | 有,内存归并 |
| 绑定 | 2 条(本地) | 1 条(精确) | 无 |
七、广播表完整场景
本质上就是在每一个库中都备份一个相同的表,以避免跨库事务
7.1 构造场景
t_dict 是订单状态字典表(5 行,几乎不变),t_order 是分片表:
status_code=1 status_name='待支付'
status_code=2 status_name='已支付'
status_code=3 status_name='已发货'
status_code=4 status_name='已完成'
查询:
SELECT o.order_id, d.status_name
FROM t_order o JOIN t_dict d ON o.status = d.status_code;
7.2 没有广播表(字典只在 ds0)
- ds0 能本地 JOIN;
- ds1 没有 t_dict,无法本地 JOIN,Proxy 只能把 ds0 的字典和 ds1 的订单拉到内存归并;
- 且在 ds0 新增状态(如"已退款")后,ds1 不知道,字典副本不一致。
7.3 配置广播表后
broadcastTables:
– t_dict
- 查询:t_dict 在 ds0、ds1 各有一份完整副本,每个库都能本地 JOIN;
- 写入自动广播: INSERT INTO t_dict VALUES (5, '已退款');
Proxy 自动向所有节点下发: → ds0: INSERT INTO t_dict VALUES (5,'已退款');
→ ds1: INSERT INTO t_dict VALUES (5,'已退款'); - 单表查询:SELECT * FROM t_dict 随便路由到一个节点即可。
7.4 选用条件
| 数据量小 | 全量副本,太大浪费存储 |
| 读多写少 | 写要广播,写频繁成本高 |
| 经常被 JOIN/查询 | 广播收益就在本地 JOIN |
| 一致性要求高 | Proxy 自动维护副本一致 |
典型:字典表、配置表、地区表。
八、统一序列号(分布式主键)
8.1 为什么分库分表后需要
分库/分表后,每个库各自自增,会产生重复主键(库 0 和库 1 都从 1 开始),因此必须有全局唯一 ID 方案。
8.2 雪花算法(Snowflake,ShardingSphere 默认)
64 位 long 型 ID,分四段:
1 bit 41 bit 时间戳 10 bit 工作机器 12 bit 序列号
┌──┬────────────────────┬────────────────┬──────────────────┐
│ 0│ 毫秒级时间戳 │ 5位数据中心+5位机器│ 同毫秒内自增序列 │
└──┴────────────────────┴────────────────┴──────────────────┘
- 1 位符号:固定 0,保证正数;
- 41 位时间戳:毫秒级,可用约 69 年;
- 10 位工作机器:5 位数据中心 + 5 位机器,共 1024 个节点;
- 12 位序列号:同一毫秒可生成 4096 个 ID。
优点:本地生成无网络开销、性能高、整体趋势递增(对 B+ 树索引友好)。
8.3 时钟回拨
机器时钟因 NTP 校时往回拨时可能生成重复 ID。(这也要求了我们不能够轻易更换时区)
处理:记录上次时间戳,回拨很小则等待追上,回拨较大则报错拒绝。
8.4 其他方案
| UUID | 简单但无序、太长,B+ 树插入性能差 |
| 数据库号段(美团 Leaf) | 批量取号,压力小 |
| Redis INCR | 简单高性能,依赖 Redis 高可用 |
| 百度 UidGenerator | 雪花变种 + RingBuffer,极高性能 |
8.5 配置
keyGenerateStrategy:
column: id
keyGeneratorName: snowflake
keyGenerators:
snowflake:
type: SNOWFLAKE
props:
worker-id: 1
插入时不指定 id,Proxy 自动填充雪花 ID。
九、读写分离 + 多集群垂直分库(其余组合可以参考)
9.1 架构形态
多个业务集群,每个集群内部是一主多从的读写分离,集群之间是垂直分库:
ShardingSphere-Proxy :3307(逻辑库 mall_db)
│
┌───────────────────────┴───────────────────────┐
▼ ▼
用户库集群 user_ds 订单库集群 order_ds
├─ user_master 写 3306 ├─ order_master 写 53311
├─ user_slave0 读 53307 └─ order_slave0 读 53312
└─ user_slave1 读 53308
│ │
t_user / t_user_log t_order / t_order_item
t_goods / t_goods_desc(垂直分表)
核心思路:先用 READWRITE_SPLITTING 把每个集群的物理主从封装成一个逻辑数据源(user_ds、order_ds),再用 SHARDING 的 actualDataNodes 引用这些逻辑数据源——两条规则叠加,路由两层级联。
9.2 完整配置
databaseName: mall_db
dataSources:
# ───── 用户库集群(一主两从) ─────
user_master:
url: jdbc:mysql://127.0.0.1:3306/db_user?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: '123456'
user_slave0:
url: jdbc:mysql://127.0.0.1:53307/db_user?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: '123456'
user_slave1:
url: jdbc:mysql://127.0.0.1:53308/db_user?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: '123456'
# ───── 订单库集群(一主一从) ─────
order_master:
url: jdbc:mysql://127.0.0.1:53311/db_order?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: '123456'
order_slave0:
url: jdbc:mysql://127.0.0.1:53312/db_order?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false
username: root
password: '123456'
rules:
# ════════ 规则 1:读写分离(把每个集群封装成逻辑数据源) ════════
– !READWRITE_SPLITTING
dataSources:
user_ds: # 用户库集群逻辑数据源
staticStrategy:
writeDataSourceName: user_master
readDataSourceNames:
– user_slave0
– user_slave1
loadBalancerName: round_robin
order_ds: # 订单库集群逻辑数据源
staticStrategy:
writeDataSourceName: order_master
readDataSourceNames:
– order_slave0
loadBalancerName: round_robin
loadBalancers:
round_robin:
type: ROUND_ROBIN
# ════════ 规则 2:垂直分库(逻辑表 → 逻辑数据源) ════════
– !SHARDING
tables:
# 用户域的表全部落在用户库集群
t_user:
actualDataNodes: user_ds.t_user
t_user_log:
actualDataNodes: user_ds.t_user_log
# 订单域的表全部落在订单库集群
t_order:
actualDataNodes: order_ds.t_order
t_order_item:
actualDataNodes: order_ds.t_order_item
# 垂直分表:商品主表与大字段扩展表(1:1),都在订单库集群
t_goods:
actualDataNodes: order_ds.t_goods
t_goods_desc:
actualDataNodes: order_ds.t_goods_desc
bindingTables:
– t_order,t_order_item
broadcastTables:
– t_dict
9.3 路由验证
| INSERT INTO t_user … | 分片→user_ds;读写分离→主 | user_master:3306 |
| SELECT * FROM t_user … | 分片→user_ds;读写分离→从(轮询) | user_slave0:53307 |
| INSERT INTO t_order … | 分片→order_ds;读写分离→主 | order_master:53311 |
| SELECT * FROM t_order … | 分片→order_ds;读写分离→从 | order_slave0:53312 |
| SELECT * FROM t_dict | 广播表,任意节点 | 随机节点 |
两级路由:先由 SHARDING 决定"去哪个业务集群",再由 READWRITE_SPLITTING 决定"走该集群的主还是从"。
9.4 关于垂直分表
垂直分表是同一个库内把大字段拆成 1:1 扩展表(如 t_goods 拆出 t_goods_desc),物理上就是两张独立表,不需要分片算法,在同一数据源下分别声明即可(见 9.2);应用层按需查询或用 goods_id 关联。若以后还要水平拆分,再为它们配置相同分片键并加入 bindingTables。
十、CAP 理论
10.1 三要素
| C:一致性 | 所有节点同一时刻看到相同数据,读总返回最新写入 |
| A:可用性 | 每个非故障节点的请求都能在有限时间内得到响应 |
| P:分区容错性 | 网络分区(中断/丢消息)时系统仍能工作 |
10.2 为什么 P 必选
网络分区不可避免,无法选择"不要 P"。实际权衡是分区发生时要 C 还是 A:
- CP:分区时拒绝部分请求保一致,牺牲可用性;
- AP:分区时各节点继续服务,允许短暂不一致,恢复后再同步。
10.3 典型系统
| CP | ZooKeeper、etcd、HBase、MongoDB(默认) |
| AP | Cassandra、Dynamo、Eureka、Redis Cluster |
对应学过的组件:
- MySQL 异步主从复制偏 AP(可能丢已提交数据);
- 半同步复制向 CP 靠拢;
- MGR 可配置 CP 能力;
- Redis Cluster 异步复制偏 AP;
- ZooKeeper(ZAB)是 CP(选举期间不可用)。
CAP 不是简单"三选二":无分区时 C 和 A 可同时满足,只有分区期间才需取舍。
10.4 BASE 理论(AP 的实践)
- Basically Available(基本可用:允许变慢、降级);
- Soft State(软状态:允许中间状态);
- Eventually Consistent(最终一致性:一段时间后所有节点一致)。
十一、分库分表带来的其他问题
| 分布式事务 | XA(2PC,偏 CP)、Saga(柔性事务,最终一致);ShardingSphere 均支持 |
| 跨库 JOIN | 绑定表、广播表、字段冗余、应用层组装 |
| 跨库分页/排序 | 各节点取数后 Proxy 归并(深分页代价大) |
| 全局唯一 ID | 雪花算法等 |
| 扩容 | 成倍扩容 + 数据迁移,或一致性哈希 |
| 聚合函数 | 各节点部分聚合后 Proxy 归并 |
十二.附录(只利用读写分离实现垂直分库)
databaseName: readwrite_splitting_db
dataSources:
write_ds_0:
url: jdbc:mysql://127.0.0.1:3306/test_db_id?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: root
password: '@Czm388512369.'
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
write_ds_1:
url: jdbc:mysql://127.0.0.1:53306/test_db_desc?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: backup
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
read_ds_0:
url: jdbc:mysql://127.0.0.1:53307/test_db_id?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: backup
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
read_ds_1:
url: jdbc:mysql://127.0.0.1:53308/test_db_desc?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: backup
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules:
– !READWRITE_SPLITTING
dataSources:
readwrite_ds_0:
staticStrategy:
writeDataSourceName: write_ds_0
readDataSourceNames:
– read_ds_0
loadBalancerName: round_robin
readwrite_ds_1:
staticStrategy:
writeDataSourceName: write_ds_1
readDataSourceNames:
– read_ds_1
loadBalancerName: round_robin
loadBalancers:
round_robin:
type: ROUND_ROBIN
| 应用视角 | 应用感知多个逻辑库,不同业务表需要切换不同库执行 | 应用只看到一个统一逻辑库,所有表都在这个库下,完全不感知底层拆分 |
| 跨库关联 | 完全不支持跨逻辑库 JOIN,应用必须自己拆两次查询再拼装 | 支持跨分片的关联查询(由 Proxy 自动改写、分发、归并),应用可以正常写 JOIN |
| 事务支持 | 跨库事务需要应用自行处理分布式事务 | 同一个逻辑库内,内置支持 XA、Seata 等分布式事务模式 |
| 后续扩展 | 某张表要做水平分片时,需要整体重构配置,改动成本高 | 本身就在分片体系内,给单张表加水平分片策略即可,架构平滑演进 |
| 配置复杂度 | 简单直观,规则少,排错容易 | 配置层级多,分片算法、路由策略复杂,排错成本高 |
这个方法大多数场景下没有分片模式好,但是也可以了解一下(博主自己突发奇想的)
网硕互联帮助中心



评论前必须登录!
注册