MySQL 集群架构与实践专题笔记

一、课程核心目标

  1. 掌握 MySQL 单机与集群模式的适用场景,理解集群架构的核心价值
  2. 精通主从复制的原理、配置流程、常用命令及问题排查
  3. 掌握高性能架构核心模式:读写分离、数据分片(垂直 / 水平分库分表)的实现逻辑
  4. 熟练使用 ShardingSphere-Proxy 中间件配置读写分离、垂直分库、水平分库分表集群
  5. 理解数据分片策略、分布式序列算法(UUID、雪花算法)的应用场景
  6. 了解 CAP/BASE 理论,能在分布式场景中进行一致性与可用性权衡

二、MySQL 集群基础认知

(一)集群的核心价值

MySQL 集群是应对高并发、大数据量场景的高可用、高性能解决方案,核心目标解决以下问题:

  1. 性能提升:分散读写负载,突破单节点性能瓶颈
  2. 高可用性:数据冗余 + 故障转移,避免单点故障导致服务中断
  3. 扩展性:通过新增节点水平扩展存储容量和处理能力
  4. 数据一致性:通过复制同步技术保证多节点数据一致
  5. 读写分离:主库承担写操作,从库分担读压力
  6. 分库分表:拆分大库大表,降低单库单表存储和查询压力
  7. 负载均衡:合理分配请求到各节点,避免单点过载

(二)单机模式 vs 集群模式

表格

对比维度 单机模式 集群模式
部署形态 单台数据库服务器承接所有读写请求 多台数据库服务器协同工作,按角色分工
性能瓶颈 单节点 CPU、内存、IO 上限明显,高并发下易过载 分散负载,支持水平扩展,突破单节点限制
可用性 单点故障直接导致业务中断,可用性极低 多节点冗余,故障节点可快速切换,可用性高
数据安全性 单节点数据丢失风险高,依赖备份恢复 多节点数据同步,数据丢失风险低
适用场景 小型应用、测试环境、低并发场景 大型应用、生产环境、高并发高可用需求场景(电商、社交、游戏等)

(三)集群核心架构分类

  1. 主从架构:一主一从、一主多从、多主多从,核心支撑读写分离
  2. 读写分离架构:主库写、从库读,通过中间件或代码路由请求
  3. 数据分片架构:垂直分片(分库 / 分表)、水平分片(分库 / 分表),拆分大库大表
  4. 混合架构:读写分离 + 数据分片结合,应对超大规模业务场景

三、主从复制(核心基础)

(一)核心角色与原理

1. 角色定义
  • 主服务器(Master):负责所有写操作(INSERT/UPDATE/DELETE)及部分简单读操作,记录二进制日志(binlog)
  • 从服务器(Slave):负责复杂读操作和数据备份,通过复制主库 binlog 并重放实现数据同步
2. 复制原理

主库将数据变更记录到 binlog,从库通过 IO 线程获取主库 binlog 并写入中继日志(Relay Log),再由 SQL 线程解析中继日志并执行,最终实现主从数据一致。

3. 关键线程
  • Master 端:Binlog Dump 线程,负责向从库推送 binlog 事件
  • Slave 端:IO 线程(读取主库 binlog 并写入中继日志)、SQL 线程(重放中继日志事件)

(二)主从复制核心流程

  1. 从库连接主库,注册自身信息(版本、时钟等)
  2. 主库为每个从库连接创建 Binlog Dump 线程
  3. 主库执行写操作时,将事件按顺序写入 binlog
  4. Binlog Dump 线程检测到 binlog 变更,推送增量事件给从库 IO 线程
  5. 从库 IO 线程将接收的事件写入中继日志
  6. 从库 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; 主库执行,查看已连接的从库列表

(五)常见问题与排查

  1. server-id 重复:修改主从库my.cnfserver-id,确保全局唯一
  2. 从库连接主库失败:检查主库防火墙是否关闭、复制用户密码是否正确、主库连接数是否充足
  3. Replica_IO_Running: Connecting:验证主库 IP / 端口正确性、复制用户权限、防火墙状态,重启从库复制(STOP REPLICA; START REPLICA;
  4. Replica_SQL_Running: NO:查看Last_SQL_Error,通常是主从数据不一致或 SQL 语法不兼容,需修复数据后重新配置复制
  5. 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 + 大规模分片集群

(二)核心注意事项

  1. 优先通过主从复制 + 读写分离解决高并发读问题,再考虑分库分表
  2. 分库分表前需明确分片键,避免后续扩容困难
  3. 尽量避免跨分片关联查询,复杂查询通过应用层聚合处理
  4. 定期监控集群状态(主从同步延迟、分片负载、中间件性能)
  5. 制定完善的备份和故障转移方案,保证高可用性
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐