半同步复制:平衡性能与数据安全

半同步复制:平衡性能与数据安全

概述

半同步复制(Semi-Synchronous Replication)在异步复制的基础上增加了一个约束:主库在提交事务后,必须等待至少一个从库确认收到并写入 Relay Log,才返回给客户端成功。 它在性能和数据安全之间取得了较好的平衡。

半同步复制的工作流程

主库                                 从库
  │                                    │
  │── 1. 事务提交                     │
  │   ├── 写入 Binlog                 │
  │   └── 不马上返回客户端            │
  │                                    │
  │── 2. 发送 Binlog 给从库           │
  │   ├── 等待从库确认收到            │
  │   └── 等待超时 rpl_semi_sync_master_timeout
  │                                    │
  │                      3. 从库收到 Binlog
  │                         I/O 线程写入 Relay Log
  │                         发送 ACK 给主库 ✅
  │                                    │
  │── 4. 收到 ACK                    │
  │   ├── 确认至少一个从库收到了      │
  │   └── 返回客户端成功 ✅           │
  │                                    │
  │                      5. SQL 线程回放(异步)
  │                         实际应用到从库数据

关键变化:步骤 1-2 之间增加了等待,步骤 4 确认后再返回客户端。

配置半同步复制

安装插件

-- 主库安装(发送端)
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

-- 从库安装(接收端)
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';

配置文件

# 主库配置
[mysqld]
plugin-load = "rpl_semi_sync_master=semisync_master.so"
rpl_semi_sync_master_enabled = ON       -- 开启半同步复制(主库)
rpl_semi_sync_master_timeout = 5000     -- 等待超时(毫秒),默认 10s
rpl_semi_sync_master_wait_for_slave_count = 1  -- 等待几个从库确认
rpl_semi_sync_master_wait_point = AFTER_SYNC   -- 等待时机

# 从库配置
[mysqld]
plugin-load = "rpl_semi_sync_slave=semisync_slave.so"
rpl_semi_sync_slave_enabled = ON        -- 开启半同步复制(从库)

运行时配置

-- 主库
SET GLOBAL rpl_semi_sync_master_enabled = ON;
SET GLOBAL rpl_semi_sync_master_timeout = 5000;

-- 从库
SET GLOBAL rpl_semi_sync_slave_enabled = ON;
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;  -- 需要重启 I/O 线程生效

验证配置

-- 主库检查
SHOW VARIABLES LIKE 'rpl_semi_sync%';
SHOW STATUS LIKE 'Rpl_semi_sync%';

-- 重点关注:
-- Rpl_semi_sync_master_status: ON     ← 半同步模式是否启用
-- Rpl_semi_sync_master_clients: 1     ← 有几个从库使用半同步
-- Rpl_semi_sync_master_yes_tx: 100    ← 成功半同步的事务数
-- Rpl_semi_sync_master_no_tx: 0       ← 降级为异步的事务数

AFTER_SYNC vs AFTER_COMMIT

MySQL 5.7+ 支持两种等待时机:

AFTER_SYNC(推荐)

1. 写入 BinlogSync
2. 等待从库 ACK            先等待再提交
3. 提交事务
4. 返回客户端成功

优势
– 所有客户端同时看到数据(主库和从库都可见)
– 主库崩溃时,所有已提交事务在从库都有
– 故障切换零数据丢失

AFTER_COMMIT(旧模式,不推荐)

1. 写入 Binlog
2. 提交事务
3. 等待从库 ACK            先提交再等待
4. 返回客户端成功

问题
– 主库提交后,其他客户端能看到新数据,但从库可能还没收到
– 主库在等待 ACK 时崩溃 → 数据存在主库但从库没有
– 故障切换可能丢数据

推荐使用 AFTER_SYNC,这是 5.7 的默认值。

超时降级

如果从库在 rpl_semi_sync_master_timeout 时间内没有返回 ACK:

主库等待从库 ACK
    │
    ├── ACK 到达 ✅ → 正常提交
    │
    └── 超时 ❌ → 降级为异步复制
        ├── 写入错误日志:Warning: 半同步超时,降级为异步
        └── 后续事务按异步方式提交
            (不会无限等待)

从库恢复后,主库会检测到并自动切换回半同步模式:

-- 主库状态变化
Rpl_semi_sync_master_status: OFF   降级为异步
Rpl_semi_sync_master_status: ON    自动恢复为半同步

优缺点

维度 说明
优点:数据更安全 主库已确认的事务,至少一个从库有
优点:自动降级 从库不可用时,自动降级为异步
优点:配置简单 插件安装 + 几行配置
缺点:性能下降 每次提交增加一个网络往返(~0.5-2ms)
缺点:不是 100% 同步 从库确认后到 SQL 应用有一段时间
缺点:网络敏感 跨机房延迟会影响写入性能

面试要点

  1. 半同步复制 = 异步复制 + 等待从库 ACK
  2. 至少一个从库确认收到 Binlog 后才返回客户端成功
  3. 超时自动降级为异步复制,保证可用性
  4. MySQL 5.7+ 推荐 AFTER_SYNC 模式
  5. 数据安全较高但性能下降:每次提交增加一个网络 RTT
  6. 适用场景:核心业务,对数据一致性和写入性能都有要求
  7. 不是从库应用后才返回,是从库收到 Relay Log 就 ACK,不等到 SQL 线程回放
© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容