Carry の Blog Carry の Blog
首页
  • Nginx
  • Prometheus
  • Iptables
  • Systemd
  • Firewalld
  • Docker
  • Sshd
  • DBA工作笔记
  • MySQL
  • Redis
  • TiDB
  • Elasticsearch
  • Python
  • Shell
  • MySQL8-SOP手册
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Carry の Blog

好记性不如烂键盘
首页
  • Nginx
  • Prometheus
  • Iptables
  • Systemd
  • Firewalld
  • Docker
  • Sshd
  • DBA工作笔记
  • MySQL
  • Redis
  • TiDB
  • Elasticsearch
  • Python
  • Shell
  • MySQL8-SOP手册
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • MySQL

    • MySQL8一键安装配置优化
    • MySQL导出CSV格式解决乱码
    • MySQL 角色管理
    • MySQL网络抓包审计
    • MySQL性能压测
    • MySQL配合Consul读写分离
    • Gh-ost重建表,清除表碎片率
    • MySQL MGR配合MySQL-router实现innodb-cluster
    • MySQL 快速分析binlog定位问题
    • MySQL执行计划分析
    • DBA常用SQL和命令整理备查
    • mysqldump实时同步数据
    • MySQL的事务隔离级别
    • MySQL存储过程批量生成数据
    • MySQL insert on duplicate key update,replace into , insert ignore的理解
    • MySQL不同字符集之间的区别和选择
    • MySQL为什么有时候会选错索引
    • MySQL死锁问题
    • MySQL使用SQL语句查重去重
    • MySQLdump逻辑备份
    • MySQL主从跳过异常GITD
    • MySQL8设置slowlog记录所有语句
    • MySQL8快速克隆插件使用指南
    • MySQL8双1设置保障安全
    • MySQL锁
    • innodb cluster安装
    • MySQL里的left join 和right join以及inner join
    • optimize table和 analyze table的区别
    • MySQL 字段的区分度计算公式
    • MySQLReplicaSet 安装
    • 脚本实现MySQL ReplicaSet 高可用
      • 说明
      • 脚本实现自动进行故障转移
    • MySQL 的Left join,Right join和Inner join 的区别
    • MySQL45讲学习笔记
  • Redis

  • Keydb

  • TiDB

  • MongoDB

  • Elasticsearch

  • Kafka

  • victoriametrics

  • BigData

  • Sqlserver

  • 数据库
  • MySQL
Carry の Blog
2023-08-13
目录

脚本实现MySQL ReplicaSet 高可用原创

# 说明

MySQL Innodb ReplicaSet 是 MySQL 团队在 2020 年推出的一款产品,用来帮助用户快速部署和管理主从复制,在数据库层仍然使用的是主从复制技术。

ReplicaSet 主要包含三个组件:MySQL Router、MySQL Server 以及 MySQL Shell 高级客户端。

MySQL Shell 负责管理 ReplicaSet 包括部署、切换、节点加入等,都可以通过内置 AdminAPI 自动化完成。

MySQL Router 是一款轻量级中间件,可在应用程序和 ReplicaSet 之间提供透明路由和读写分离功能。

基于系统的高可用要求,ReplicaSet 可提供 RTO 等于数分钟,RPO < 1 秒 的高可用性,适用于对高可用要求不高的场景。因为它无法自动进行故障转移,当发生故障时,需要运维人员通过 AdminAPI 进行主备切换。另外 MySQL Router 读写分离提供的是两个端口 r/w 和 ro 组,如果要使用读写分离功能,则需要应用适配。

# 脚本实现自动进行故障转移

点击查看代码
#!/bin/bash
# MySQL 用户名
mysql_user='dba_rsadmin'
# 候选主机列表,这些是可能成为主库的备选主机
candidates=(mysql-01 mysql-02 mysql-03)
# 检查间隔时间(秒)
interval=2
# 最大检查次数
max_checks=5
# 存储状态信息的文件名
status_file=${0//.sh/}.status
# 日志函数,用于输出错误信息
log_err() {
    echo $(date "+%F %T") $* >&2;
}
# 获取复制集群状态信息的函数
replicaset_status() {
    for node in ${candidates[@]}; do
        # 使用 mysqlsh 工具连接到候选主机,并获取复制集群状态信息
        mysqlsh ${mysql_user}@${node}:3366 -e 'print(dba.getReplicaSet().status())'
        # 如果命令执行成功,则返回 0,表示成功获取状态信息
        [ $? -eq 0 ] && return 0
    done
    # 如果无法获取状态信息,则返回 1
    return 1
}
# 从状态文件中获取主库地址的函数
get_primary_address() {
    jq -r '.replicaSet.topology[]|select(.instanceRole == "PRIMARY")|.address' ${status_file}
}
# 从状态文件中获取从库地址的函数
get_secondary_addresses() {
    jq -r '.replicaSet.topology[]|select(.instanceRole == "SECONDARY")|.address' ${status_file}
}
# 对指定主机进行健康检查的函数
health_check() {
    mysqlsh --sql ${mysql_user}@${1} -e "select 1" 2>&1 >/dev/null
}
# 执行主库切换的函数
do_failover() {
    mysqlsh ${mysql_user}@${1} -e 'dba.getReplicaSet().forcePrimaryInstance()'
}
# 主函数
main() {
    while :; do
        checks=0
        while [ ${checks} -lt ${max_checks} ]; do
            # 获取复制集群状态,并将结果保存到状态文件中
            replicaset_status > ${status_file} 2>/dev/null
            # 检查是否成功获取状态信息
            if [ $? -eq 0 ]; then
                # 获取当前主库地址
                prim=$(get_primary_address)
                # 对当前主库进行健康检查
                health_check ${prim}
                # 如果主库不可用
                if [ $? -ne 0 ]; then
                    checks=$((checks+1))
                    sleep ${interval}
                else
                    # 主库可用,跳出循环
                    break
                fi
            else
                log_err "无法获取复制集群信息。"
                exit 1
            fi
        done
        
        if [ ${checks} -eq ${max_checks} ]; then
            log_err "连续 ${max_checks} 次检查主库不可用,执行主库切换。"
            # 遍历从库地址列表
            for sec in $(get_secondary_addresses); do
                # 对从库进行健康检查
                health_check ${sec}
                if [ $? -eq 0 ]; then
                    # 如果从库可用,则执行主库切换操作
                    do_failover ${sec}
                    case $? in
                        0)
                            log_err "主库切换成功,当前主库是 ${sec}"
                            break
                            ;;
                        *)
                            log_err "主库切换失败"
                            break
                            ;;
                    esac
                fi
            done
        fi
        
        # 输出主库健康检查通过的信息
        log_err "健康检查通过,当前主库是 ${prim}"
        
        # 等待一段时间后再进行下一次检查
        sleep ${interval}
    done
}
# 调用主函数开始执行脚本
main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
上次更新: 4/24/2025

← MySQLReplicaSet 安装 MySQL 的Left join,Right join和Inner join 的区别→

最近更新
01
tidb fast ddl
04-04
02
TiDB配置文件调优 原创
04-03
03
如何移除TiDB中的表分区 原创
04-03
更多文章>
Theme by Vdoing
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式