MySQL第五课时
MySQL 集群架构与实践专题笔记
一、课程核心目标
- 掌握 MySQL 单机与集群模式的适用场景,理解集群架构的核心价值
- 精通主从复制的原理、配置流程、常用命令及问题排查
- 掌握高性能架构核心模式:读写分离、数据分片(垂直 / 水平分库分表)的实现逻辑
- 熟练使用 ShardingSphere-Proxy 中间件配置读写分离、垂直分库、水平分库分表集群
- 理解数据分片策略、分布式序列算法(UUID、雪花算法)的应用场景
- 了解 CAP/BASE 理论,能在分布式场景中进行一致性与可用性权衡
二、MySQL 集群基础认知
(一)集群的核心价值
MySQL 集群是应对高并发、大数据量场景的高可用、高性能解决方案,核心目标解决以下问题:
- 性能提升:分散读写负载,突破单节点性能瓶颈
- 高可用性:数据冗余 + 故障转移,避免单点故障导致服务中断
- 扩展性:通过新增节点水平扩展存储容量和处理能力
- 数据一致性:通过复制同步技术保证多节点数据一致
- 读写分离:主库承担写操作,从库分担读压力
- 分库分表:拆分大库大表,降低单库单表存储和查询压力
- 负载均衡:合理分配请求到各节点,避免单点过载
(二)单机模式 vs 集群模式
表格
| 对比维度 | 单机模式 | 集群模式 |
|---|---|---|
| 部署形态 | 单台数据库服务器承接所有读写请求 | 多台数据库服务器协同工作,按角色分工 |
| 性能瓶颈 | 单节点 CPU、内存、IO 上限明显,高并发下易过载 | 分散负载,支持水平扩展,突破单节点限制 |
| 可用性 | 单点故障直接导致业务中断,可用性极低 | 多节点冗余,故障节点可快速切换,可用性高 |
| 数据安全性 | 单节点数据丢失风险高,依赖备份恢复 | 多节点数据同步,数据丢失风险低 |
| 适用场景 | 小型应用、测试环境、低并发场景 | 大型应用、生产环境、高并发高可用需求场景(电商、社交、游戏等) |
(三)集群核心架构分类
- 主从架构:一主一从、一主多从、多主多从,核心支撑读写分离
- 读写分离架构:主库写、从库读,通过中间件或代码路由请求
- 数据分片架构:垂直分片(分库 / 分表)、水平分片(分库 / 分表),拆分大库大表
- 混合架构:读写分离 + 数据分片结合,应对超大规模业务场景
三、主从复制(核心基础)
(一)核心角色与原理
1. 角色定义
- 主服务器(Master):负责所有写操作(INSERT/UPDATE/DELETE)及部分简单读操作,记录二进制日志(binlog)
- 从服务器(Slave):负责复杂读操作和数据备份,通过复制主库 binlog 并重放实现数据同步
2. 复制原理
主库将数据变更记录到 binlog,从库通过 IO 线程获取主库 binlog 并写入中继日志(Relay Log),再由 SQL 线程解析中继日志并执行,最终实现主从数据一致。
3. 关键线程
- Master 端:Binlog Dump 线程,负责向从库推送 binlog 事件
- Slave 端:IO 线程(读取主库 binlog 并写入中继日志)、SQL 线程(重放中继日志事件)
(二)主从复制核心流程
- 从库连接主库,注册自身信息(版本、时钟等)
- 主库为每个从库连接创建 Binlog Dump 线程
- 主库执行写操作时,将事件按顺序写入 binlog
- Binlog Dump 线程检测到 binlog 变更,推送增量事件给从库 IO 线程
- 从库 IO 线程将接收的事件写入中继日志
- 从库 SQL 线程读取中继日志,解析为 SQL 并执行,同步数据
(三)主从复制配置实战(Docker 环境)
1. 环境规划
- 主库:容器名
bit-mysql-master,端口 53306 - 从库 1:容器名
bit-mysql-slave1,端口 53307 - 从库 2:容器名
bit-mysql-slave2,端口 53308 - 核心要求:主从
server-id唯一,关闭防火墙,主库开启 binlog
2. 主库配置步骤
(1)创建并启动主库容器
bash
运行
# 创建目录
mkdir -p /bit/mysql/master/conf /bit/mysql/master/mysql
# 启动容器
docker run -d \
-p 53306:3306 \
-v /bit/mysql/master/conf:/etc/mysql/conf.d \
-v /bit/mysql/master/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name bit-mysql-master \
mysql:8.0.38
(2)配置主库my.cnf(核心)
在/bit/mysql/master/conf目录创建my.cnf:
ini
[mysqld]
server-id=13803306 # 唯一ID,不可与从库重复
log-bin=binlog # 开启binlog,日志基本名
binlog_format=ROW # binlog格式(推荐ROW,保证主从一致)
binlog_expire_logs_seconds=864000 # binlog过期时间(10天)
sync-binlog=1 # 事务提交时刷盘,保证binlog不丢失
# 可选:指定复制/忽略的数据库
# binlog-do-db=bit_db
# binlog-ignore-db=mysql
(3)重启主库并创建复制用户
bash
运行
docker restart bit-mysql-master
# 进入容器
docker exec -it bit-mysql-master env LANG=C.UTF-8 /bin/bash
# 登录MySQL
mysql -uroot -p123456
# 创建复制用户
create user 'bit_slave'@'%' identified with mysql_native_password by '123456';
# 授予复制权限
grant REPLICATION SLAVE on *.* to 'bit_slave'@'%';
# 刷新权限
flush privileges;
# 查看主库状态(记录File和Position,从库配置需用到)
show master status;
3. 从库配置步骤(以 slave1 为例)
(1)创建并启动从库容器
bash
运行
mkdir -p /bit/mysql/slave1/conf /bit/mysql/slave1/mysql
docker run -d \
-p 53307:3306 \
-v /bit/mysql/slave1/conf:/etc/mysql/conf.d \
-v /bit/mysql/slave1/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name bit-mysql-slave1 \
mysql:8.0.38
(2)配置从库my.cnf
在/bit/mysql/slave1/conf目录创建my.cnf:
ini
[mysqld]
server-id=13803307 # 唯一ID,与主库、其他从库不同
log-bin=binlog # 可选,从库如需作为其他从库的主库则开启
binlog_format=ROW
binlog_expire_logs_seconds=864000
sync-binlog=1
# 从库专属配置
relay-log=relay-bin # 中继日志基本名
skip-replica-start=ON # 启动不自动开始复制,手动控制(MySQL8.0.26+)
# log-replica-updates=ON # 可选,链式复制时开启(从库同步给其他从库)
(3)重启从库并配置主从关系
bash
运行
docker restart bit-mysql-slave1
# 进入容器登录MySQL
docker exec -it bit-mysql-slave1 env LANG=C.UTF-8 /bin/bash
mysql -uroot -p123456
# 配置主从关系(使用主库show master status的File和Position)
CHANGE MASTER TO
MASTER_HOST = '192.168.80.138',
MASTER_PORT = 53306,
MASTER_USER = 'bit_slave',
MASTER_PASSWORD = '123456',
MASTER_LOG_FILE = 'binlog.000014', # 主库的File值
MASTER_LOG_POS = 157; # 主库的Position值
# 启动复制
START REPLICA;
# 查看从库状态(核心关注Replica_IO_Running和Replica_SQL_Running是否为YES)
SHOW REPLICA STATUS\G
4. 复制测试
sql
# 主库创建数据库和表并插入数据
create database bit_db character set utf8mb4;
use bit_db;
create table t_user (id bigint primary key auto_increment, name varchar(20) not null);
insert into t_user (name) values ('张三'), ('李四');
# 从库查询,验证数据同步
use bit_db;
select * from t_user; # 应显示主库插入的数据
(四)主从复制常用命令
表格
| 操作场景 | 命令 | 说明 |
|---|---|---|
| 查看主库状态 | show master status; |
显示当前 binlog 文件、位置等核心信息 |
| 查看从库状态 | show replica status\G |
查看 IO/SQL 线程状态、错误信息等 |
| 启动复制 | START REPLICA; |
MySQL8.0.26+,旧版本用START SLAVE; |
| 停止复制 | STOP REPLICA; |
旧版本用STOP SLAVE; |
| 重置从库复制信息 | RESET REPLICA; |
清空中继日志,重置复制状态 |
| 重置主库 binlog | RESET MASTER; |
清空所有 binlog,主库慎用 |
| 查看连接的从库 | SHOW REPLICAS; |
主库执行,查看已连接的从库列表 |
(五)常见问题与排查
- server-id 重复:修改主从库
my.cnf的server-id,确保全局唯一 - 从库连接主库失败:检查主库防火墙是否关闭、复制用户密码是否正确、主库连接数是否充足
- Replica_IO_Running: Connecting:验证主库 IP / 端口正确性、复制用户权限、防火墙状态,重启从库复制(
STOP REPLICA; START REPLICA;) - Replica_SQL_Running: NO:查看
Last_SQL_Error,通常是主从数据不一致或 SQL 语法不兼容,需修复数据后重新配置复制 - binlog 日志损坏:备份主库数据并在从库恢复,重构主从关系
四、高性能架构核心模式
(一)读写分离
1. 核心概念
将数据库读写操作分离到不同节点:主库处理写操作(INSERT/UPDATE/DELETE)和少量核心读操作,从库处理大量普通读操作,通过负载均衡分发读请求,提升系统并发处理能力。
2. 核心特点
- 负载均衡:分散读压力,主库专注写操作,从库集群支撑高并发读
- 数据同步:依赖主从复制保证从库数据一致性,存在轻微同步延迟
- 故障转移:主库故障时可将从库提升为主库,保证服务连续性
- 策略灵活:静态分离(代码固定路由)、动态分离(中间件智能路由)
3. 适用场景
- 读多写少场景(如电商商品列表查询、新闻资讯浏览)
- 高并发读需求,单节点读性能不足
- 需要水平扩展读能力的场景
4. 实现方式
表格
| 实现方式 | 优点 | 缺点 |
|---|---|---|
| 程序代码封装 | 灵活可控,无额外中间件依赖 | 侵入业务代码,维护成本高,扩展性差 |
| 中间件封装 | 透明化接入,不侵入代码,扩展性强 | 需部署维护中间件,增加系统复杂度 |
5. 主流中间件
表格
| 中间件 | 特点 | 状态 |
|---|---|---|
| ShardingSphere-Proxy | 开源活跃,支持读写分离、分片、加密等,兼容多数据库 | 推荐生产使用 |
| MyCat | 国内开源,功能全面 | 停止更新 |
| Atlas | 360 出品,轻量易用 | 停止更新 |
| Vitess | Google 开源,支持大规模集群 | 社区活跃度一般 |
(二)数据分片
1. 核心概念
将单一数据库或表中的数据,按某种规则分散到多个数据库或表中(称为 “分片”),每个分片仅存储部分数据,从而突破单库单表的存储和性能瓶颈。
2. 分片分类与实现
(1)垂直分片(按业务维度拆分)
-
垂直分库:按业务模块拆分数据库,如电商系统拆分为用户库(user_db)、订单库(order_db)、商品库(goods_db)
- 特点:专库专用,分散单库负载,降低业务耦合
- 适用场景:业务模块清晰、模块间关联度低
- 缺点:跨库关联查询复杂,需通过中间件或应用层处理
-
垂直分表:将一张表中不常用或大字段拆分到单独表,如商品表(t_goods)拆分为基础信息表(t_goods_base)和详情表(t_goods_detail)
- 特点:减少主表字段数量,提升查询效率,节省存储
- 适用场景:单表字段过多、大字段(如 text)占用大量存储空间
- 缺点:查询完整数据需关联表,增加操作复杂度
(2)水平分片(按数据维度拆分)
-
水平分表:将一张表中的数据按规则拆分到同一数据库的多张表,如订单表(t_order)按 ID 取模拆分为 t_order0 和 t_order1
- 特点:单表数据量减少,索引深度降低,查询速度提升
- 适用场景:单表数据量过大(如超过 500 万行),但服务器资源充足
- 缺点:跨表查询需聚合结果,分页查询复杂
-
水平分库:将一张表中的数据按规则拆分到多个数据库的多张表,如订单表按用户 ID 取模拆分为 server_order0.t_order0、server_order0.t_order1、server_order1.t_order0、server_order1.t_order1
- 特点:同时分散存储和计算负载,支持大规模扩展
- 适用场景:单库单表均无法满足性能要求,超大规模数据存储
- 缺点:跨库跨表查询复杂,分布式事务处理难度大
3. 分片策略(核心规则)
表格
| 策略类型 | 实现方式 | 适用场景 | 优点 | 缺点 |
|---|---|---|---|---|
| 取模分片 | 按分片键(如 ID、用户 ID)取模(mod) | 数据分布均匀,查询条件含分片键 | 简单高效,负载均衡 | 扩容时需重新分片,数据迁移复杂 |
| 范围分片 | 按分片键范围(如时间、ID 区间)拆分 | 时间序列数据(如订单创建时间)、范围查询频繁 | 扩容简单,范围查询高效 | 数据可能分布不均(热点区间负载高) |
| 哈希分片 | 按分片键哈希值取模 | 分片键为字符串(如订单号),需均匀分布 | 数据分布均匀,支持字符串分片键 | 哈希值计算有开销,无范围查询优化 |
| 列表分片 | 按分片键枚举值拆分(如按地区、用户类型) | 业务维度明确,需按固定维度隔离数据 | 符合业务逻辑,隔离性好 | 新增枚举值需扩展分片,灵活性差 |
4. 关键注意事项
- 分片键选择:优先选择查询频繁、分布均匀的字段(如用户 ID、订单号)
- 数据一致性:依赖中间件或分布式事务保证跨分片数据一致性
- 跨分片查询:通过中间件聚合结果,避免复杂关联查询
- 扩容规划:提前设计分片扩容方案(如一致性哈希减少数据迁移)
(三)混合架构(读写分离 + 数据分片)
将读写分离与数据分片结合,主库集群处理写操作,从库集群按分片规则处理读操作,适用于超大规模、高并发、大数据量的核心业务场景(如电商交易系统、大型社交平台)。
五、ShardingSphere-Proxy 实战(核心中间件)
(一)工具介绍
ShardingSphere-Proxy 是 Apache 顶级项目,定位为透明化数据库代理,支持 MySQL、PostgreSQL 等数据库,提供读写分离、数据分片、分布式事务、数据加密等功能,应用程序可通过标准 SQL 协议连接,无需修改代码。
核心优势
- 透明化接入,应用程序无感知
- 支持多种分片策略和负载均衡算法
- 兼容主流数据库和 SQL 语法
- 可扩展,支持自定义分片算法和功能
(二)安装与部署(Docker 方式)
1. 环境准备
- 安装 Docker(参考前文 Docker 安装步骤)
- 下载 MySQL 驱动(
mysql-connector-j-8.0.33.jar),放入代理扩展目录
2. 创建并启动容器
bash
运行
# 创建映射目录
mkdir -p /bit/shardingsphere/proxy/conf /bit/shardingsphere/proxy/ext-lib /bit/shardingsphere/proxy/logs
# 复制MySQL驱动到ext-lib目录
cp mysql-connector-j-8.0.33.jar /bit/shardingsphere/proxy/ext-lib/
# 启动容器
docker run -d \
-p 3307:3307 \
-v /bit/shardingsphere/proxy/conf:/opt/shardingsphere-proxy/conf \
-v /bit/shardingsphere/proxy/ext-lib:/opt/shardingsphere-proxy/ext-lib \
-v /bit/shardingsphere/proxy/logs:/opt/shardingsphere-proxy/logs \
-e JVM_OPTS="-Xms256m -Xmx256m -Xmn128m" \
--name ss-proxy \
apache/shardingsphere-proxy:5.3.2
3. 基础配置(server.yaml)
修改/bit/shardingsphere/proxy/conf/server.yaml,配置用户授权和全局属性:
yaml
mode:
type: Standalone # 单机模式
authority:
users:
- user: root@% # 用户名,支持通配符%
password: 123456 # 密码
privilege:
type: ALL_PERMITTED # 授予所有权限
props:
sql-show: true # 显示执行的SQL语句,便于调试
proxy-mysql-default-version: 8.0.38 # 兼容MySQL版本
4. 启动验证
bash
运行
# 启动容器
docker start ss-proxy
# 测试连接(使用MySQL客户端)
mysql -uroot -p123456 -h192.168.80.138 -P3307
# 查看数据库
show databases; # 应显示information_schema、mysql、shardingsphere等系统库
(三)实战 1:配置读写分离
1. 架构规划
- 主库:bit-mysql-master(53306),写数据源(write_ds)
- 从库 1:bit-mysql-slave1(53307),读数据源(read_ds_0)
- 从库 2:bit-mysql-slave2(53308),读数据源(read_ds_1)
- 代理逻辑库:bit_proxy_db
- 负载均衡策略:随机(RANDOM)、轮询(ROUND_ROBIN)、权重(WEIGHT)
2. 配置文件(config-readwrite-splitting.yaml)
yaml
databaseName: bit_proxy_db # 代理逻辑库名
dataSources:
write_ds: # 主库数据源
url: jdbc:mysql://192.168.80.138:53306/bit_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
read_ds_0: # 从库1数据源
url: jdbc:mysql://192.168.80.138:53307/bit_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
read_ds_1: # 从库2数据源
url: jdbc:mysql://192.168.80.138:53308/bit_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules:
!READWRITE_SPLITTING
dataSources:
readwrite_ds: # 读写分离规则名
staticStrategy:
writeDataSourceName: write_ds # 写数据源
readDataSourceNames: # 读数据源列表
- read_ds_0
- read_ds_1
loadBalancerName: random # 负载均衡策略(random/round_robin/weight)
loadBalancers:
random:
type: RANDOM # 随机策略
round_robin:
type: ROUND_ROBIN # 轮询策略
weight:
type: WEIGHT # 权重策略
props:
read_ds_0: 2.0 # 从库1权重
read_ds_1: 1.0 # 从库2权重
3. 测试验证
bash
运行
# 启动代理容器
docker restart ss-proxy
# 连接代理
mysql -uroot -p123456 -h192.168.80.138 -P3307
# 切换到逻辑库
use bit_proxy_db;
# 写入数据(路由到write_ds)
insert into t_user (name) values ('test_rw');
# 多次查询(路由到read_ds_0或read_ds_1)
select * from t_user;
# 查看代理日志,验证路由是否正确
docker exec -it ss-proxy tail -f /opt/shardingsphere-proxy/logs/stdout.log
(四)实战 2:配置垂直分库
1. 架构规划
- 用户库:server-user(53310),存储 t_user 表(user_db)
- 订单库:server-order(53311),存储 t_order 表(order_db)
- 代理逻辑库:sharding_db
- 核心:按业务模块拆分数据库,代理自动路由表操作到对应数据源
2. 前置准备
bash
运行
# 创建用户库容器
docker run -d \
-p 53310:3306 \
-v /bit/mysql/user/conf:/etc/mysql/conf.d \
-v /bit/mysql/user/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-user \
mysql:8.0.38
# 进入用户库创建表
docker exec -it server-user env LANG=C.UTF-8 /bin/bash
mysql -uroot -p123456
create database user_db character set utf8mb4;
use user_db;
create table t_user (id bigint primary key auto_increment, name varchar(20));
# 创建订单库容器
docker run -d \
-p 53311:3306 \
-v /bit/mysql/order/conf:/etc/mysql/conf.d \
-v /bit/mysql/order/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-order \
mysql:8.0.38
# 进入订单库创建表
docker exec -it server-order env LANG=C.UTF-8 /bin/bash
mysql -uroot -p123456
create database order_db character set utf8mb4;
use order_db;
create table t_order (id bigint primary key auto_increment, order_no varchar(30), user_id bigint, amount decimal(12,2));
3. 代理配置(config-sharding.yaml)
yaml
databaseName: sharding_db # 逻辑库名
dataSources:
server_user: # 用户数据源
url: jdbc:mysql://192.168.80.138:53310/user_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
server_order: # 订单数据源
url: jdbc:mysql://192.168.80.138:53311/order_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules:
- !SHARDING
tables:
t_user: # 逻辑表t_user
actualDataNodes: server_user.t_user # 真实数据节点(数据源.表名)
t_order: # 逻辑表t_order
actualDataNodes: server_order.t_order # 真实数据节点
4. 测试验证
bash
运行
# 重启代理
docker restart ss-proxy
# 连接代理
mysql -uroot -p123456 -h192.168.80.138 -P3307
use sharding_db;
# 插入用户数据(路由到server_user)
insert into t_user (name) values ('张三');
# 插入订单数据(路由到server_order)
insert into t_order (order_no, user_id, amount) values ('BIT001', 1, 20.00);
# 查询验证
select * from t_user; # 从server_user查询
select * from t_order; # 从server_order查询
(五)实战 3:配置水平分库分表
1. 架构规划
- 订单库 0:server-order0(63310),存储 t_order0、t_order1(order_db)
- 订单库 1:server-order1(63311),存储 t_order0、t_order1(order_db)
- 代理逻辑库:sharding_db
- 分片规则:
- 分库:按 user_id 取模(user_id%2),路由到 server-order0 或 server-order1
- 分表:按 order_no 哈希取模(HASH_MOD),路由到 t_order0 或 t_order1
2. 前置准备
bash
运行
# 创建订单库0容器
docker run -d \
-p 63310:3306 \
-v /bit/mysql/order0/conf:/etc/mysql/conf.d \
-v /bit/mysql/order0/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-order0 \
--restart always \
mysql:8.0.38
# 进入订单库0创建表
docker exec -it server-order0 env LANG=C.UTF-8 /bin/bash
mysql -uroot -p123456
create database order_db character set utf8mb4;
use order_db;
create table t_order0 (id bigint primary key, order_no varchar(30), user_id bigint, amount decimal(12,2));
create table t_order1 (id bigint primary key, order_no varchar(30), user_id bigint, amount decimal(12,2));
# 创建订单库1容器(步骤同上,端口63311,容器名server-order1)
docker run -d \
-p 63311:3306 \
-v /bit/mysql/order1/conf:/etc/mysql/conf.d \
-v /bit/mysql/order1/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--name server-order1 \
--restart always \
mysql:8.0.38
# 进入订单库1创建表(同订单库0)
3. 代理配置(config-sharding.yaml)
yaml
databaseName: sharding_db
dataSources:
server_user: # 保留用户数据源
url: jdbc:mysql://192.168.80.138:53310/user_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
server_order0: # 订单库0数据源
url: jdbc:mysql://192.168.80.138:63310/order_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
server_order1: # 订单库1数据源
url: jdbc:mysql://192.168.80.138:63311/order_db?characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&useSSL=false
username: root
password: 123456
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
rules:
- !SHARDING
tables:
t_user:
actualDataNodes: server_user.t_user
t_order:
actualDataNodes: server_order${0..1}.t_order${0..1} # 行表达式,匹配4个分片
databaseStrategy: # 分库策略
standard:
shardingColumn: user_id # 分库键
shardingAlgorithmName: alg_mod # 分库算法(取模)
tableStrategy: # 分表策略
standard:
shardingColumn: order_no # 分表键
shardingAlgorithmName: alg_hash_mod # 分表算法(哈希取模)
keyGenerateStrategy: # 分布式序列策略
column: id # 主键列
keyGeneratorName: alg_snowflake # 雪花算法
shardingAlgorithms:
alg_mod: # 取模算法
type: MOD
props:
sharding-count: 2 # 分库数量
alg_hash_mod: # 哈希取模算法
type: HASH_MOD
props:
sharding-count: 2 # 分表数量
keyGenerators:
alg_snowflake: # 雪花算法配置
type: SNOWFLAKE
4. 测试验证
bash
运行
# 重启代理
docker restart ss-proxy
# 连接代理插入数据
mysql -uroot -p123456 -h192.168.80.138 -P3307
use sharding_db;
# 插入订单(user_id=1→server-order1,order_no=BIT001→t_order0)
insert into t_order (order_no, user_id, amount) values ('BIT001', 1, 20.00);
# 插入订单(user_id=2→server-order0,order_no=BIT002→t_order1)
insert into t_order (order_no, user_id, amount) values ('BIT002', 2, 30.00);
# 查询所有订单(代理聚合4个分片结果)
select * from t_order;
# 条件查询(按分片键路由到指定分片)
select * from t_order where user_id=1; # 仅查询server-order1的两个表
(六)高级特性配置
1. 分布式序列(解决主键重复)
- UUID:全局唯一,但无序,不适合作为主键索引
- 雪花算法(SNOWFLAKE):生成 64 位有序长整型 ID,含时间戳、工作进程 ID、序列号,支持高并发,适合作为主键
- 配置见水平分库分表示例,插入数据时无需指定 ID,代理自动生成
2. 绑定表(优化关联查询)
将分片规则一致的表绑定,避免关联查询时产生笛卡尔积,提升查询效率。例如 t_order 和 t_order_item(订单详情表),配置如下:
yaml
rules:
- !SHARDING
tables:
# ... 省略t_user、t_order配置
t_order_item:
actualDataNodes: server_order${0..1}.t_order_item${0..1}
databaseStrategy:
standard:
shardingColumn: user_id
shardingAlgorithmName: alg_mod
tableStrategy:
standard:
shardingColumn: order_no
shardingAlgorithmName: alg_hash_mod
bindingTables: # 绑定表配置
- t_order,t_order_item
3. 广播表(全局一致小表)
适用于数据量小、变更少、需全局一致的表(如字典表 t_dict),代理自动同步所有分片的增删改操作,查询时从任意分片获取数据:
yaml
rules:
- !SHARDING
# ... 省略其他配置
broadcastTables:
- t_dict # 广播表名
六、分布式系统理论基础
(一)CAP 理论
1. 核心概念
- 一致性(Consistency):写操作完成后,所有读操作均返回最新数据
- 可用性(Availability):任何请求都能在合理时间内返回有效响应
- 分区容错性(Partition Tolerance):网络分区(节点通信失败)时,系统仍能正常运行
2. 核心结论
分布式系统中网络分区不可避免(必须保证 P),因此只能在一致性(C)和可用性(A)之间权衡:
- CP 系统:保证一致性和分区容错性,牺牲可用性。适用于数据一致性要求极高的场景(如银行转账、支付系统)
- AP 系统:保证可用性和分区容错性,牺牲强一致性(最终一致)。适用于可用性要求极高的场景(如社交、电商商品列表)
(二)BASE 理论
是 CAP 理论的补充,核心思想是 “最终一致性”:
- 基本可用(Basically Available):故障时保证核心功能可用,非核心功能降级
- 软状态(Soft State):允许数据存在中间状态(如主从同步延迟)
- 最终一致性(Eventually Consistent):经过一段时间后,所有节点数据最终一致
(三)应用场景选择
- 金融、支付等核心业务:选择 CP 系统,优先保证数据一致性
- 社交、电商非核心业务:选择 AP 系统,优先保证服务可用性
七、总结与选型建议
(一)架构选型指南
表格
| 业务规模 | 推荐架构 | 核心组件 |
|---|---|---|
| 小型应用(并发 < 1k) | 单机模式 | 单台 MySQL |
| 中型应用(并发 1k-10k) | 主从复制 + 读写分离 | MySQL 主从集群 + ShardingSphere-Proxy |
| 大型应用(并发 10k-100k) | 读写分离 + 垂直分库 | ShardingSphere-Proxy + 多主从集群 |
| 超大型应用(并发 > 100k) | 读写分离 + 水平分库分表 | ShardingSphere-Proxy + 大规模分片集群 |
(二)核心注意事项
- 优先通过主从复制 + 读写分离解决高并发读问题,再考虑分库分表
- 分库分表前需明确分片键,避免后续扩容困难
- 尽量避免跨分片关联查询,复杂查询通过应用层聚合处理
- 定期监控集群状态(主从同步延迟、分片负载、中间件性能)
- 制定完善的备份和故障转移方案,保证高可用性
更多推荐
所有评论(0)