Keepalived 案例2 — MySQL主从复制 + keepalived

前言

关于 MySQL 主从复制的原理,请参阅以前的 《Redis进阶篇04 — 复制技术(一)MySQL》

Q:为什么主从复制一定要搭配 keepalived ?

复制(Replication):一种将一组数据从一个数据源拷贝到另外一个或多个数据源的备份技术。在 MySQL 主从复制中,复制能实现数据备份、读写分离(提高并发处理能力)、部分高可用(相比单机单实例)。在实际的业务环境中,主从复制的 master 出现故障时,需要人为手动的进行切换,但有些关键业务需要一些可靠性标准——2个9标准(99%);3个9标准(99.9%)等。因此我们需要出现故障时全程自动切换,这也是为什么需要 keepalived 的原因。

由前面文章可知主从复制的原则:

  • 每个 Slave(replica) 只能有一个 Master(source)
  • 每个 Slave(replica) 只能有唯一的 server-id
  • 每个 Master(source) 可以有多个 Slave(replica)
术语更新
从 Mysql Server 8.0.23 开始,不再以 master 和 slave 来区分主从,而是使用 source 和 replica 来替代这些术语,部分语法也发生了一些变化。
术语解释
在默认的异步复制操作中,我们把数据的来源称为 source server,把复制数据之后的接收服务器称为 replica server。

基本信息列表:

OS COMMAND/GUI 真实 IP 部署软件 扮演角色 VIP 初始主备
RL 8.7 COMMAND 10.1.1.3/24 Mysql Server V8.0.33 source 10.1.1.15/24 Master
RL 8.7 COMMAND 10.1.1.4/24 Mysql Server V8.0.33 replica 10.1.1.15/24 Backup
注意
实际情况下,不管是 MySQL 主从复制还是 MySQL Cluster,其所需的硬件规格最好统一(CPU的核心数、内存大小和硬盘大小等)。其次,网络速度太慢以及延迟过大都会影响复制数据的效率。

MySQL 的安装与配置

您的安装方式不必与作者相同。

10.1.1.3/24 安装和配置 MySQL

以下为操作步骤:

# 创建伪用户(0<uid<1000)和伪组(0<gid<1000)
Shell > groupadd -r mysql && useradd -r -g mysql -s /sbin/nologin mysql

# 安装依赖,\ 表示命令未结束
Shell > dnf -y  install libaio ncurses-compat-libs  ncurses-devel make cmake gcc bison git libtirpc-devel \
openssl openssl-devel rpcgen  gcc-toolset-12-gcc  gcc-toolset-12-gcc-c++

# 开始源代码编译
Shell > wget -c https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-boost-8.0.33.tar.gz

Shell > tar -zvxf mysql-boost-8.0.33.tar.gz  -C  /usr/local/src/ 

Shell > cd /usr/local/src/mysql-8.0.33/  &&  mkdir build  &&  cd build  &&  cmake .. \
-DDEFAULT_CHARSET=utf8mb4  \
-DDEFAULT_COLLATION=utf8mb4_0900_ai_ci  \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql/   \
-DCMAKE_BUILD_TYPE=RelWithDebInfo  \
-DENABLED_LOCAL_INFILE=1  \
-DMYSQL_TCP_PORT=3306  \
-DWITH_BOOST=/usr/local/src/mysql-8.0.33/boost/  \
-DMYSQL_DATADIR=/usr/local/mysql/data  \
&&  make  &&  make install 

大约需要等待 1.5 小时,MySQL 才完成编译和安装。

基本配置如下:

Shell > chmod -R 755 /usr/local/mysql/

Shell > chown -R mysql:mysql /usr/local/mysql/

# 执行初始化,生成数据目录以及初始的 root 密码
Shell > /usr/local/mysql/bin/mysqld  --initialize  --user=mysql  --basedir=/usr/local/mysql  \
--datadir=/usr/local/mysql/data

# 添加配置文件 /etc/my.cnf
Shell > vim /etc/my.cnf
[client]
port = 3306
socket = /tmp/mysql.sock

[mysqld]
server-id = 1
port = 3306
socket = /tmp/mysql.sock
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
user = mysql
log-error = /usr/local/mysql/data/mysqld_start.err
bind-address = *
default-storage-engine = INNODB
group-concat-max-len = 102400
skip-name-resolve
back-log = 151
max-connections = 700
wait-timeout = 90
max-allowed-packet = 100M
read-buffer-size = 512K
sync-binlog = 1
innodb-buffer-pool-size = 1G
log-bin = /usr/local/mysql/data/source-binlog
read-only = 0
binlog-expire-logs-seconds = 2592000
binlog-format = ROW

[mysqldump]
quick

一些关键配置项的说明:

  • server-id = 1,标识当前数据库实例的唯一编号,主要是为了区别不同的 MySQL 服务器
  • default-storage-engine = INNODB – 默认使用的存储引擎
  • group-concat-max-len = 102400 – GROUP_CONCAT( )函数允许的最大结果长度(字节),默认 1024。通常我们都建议您加大该参数项的值
  • back-log = 151 – 在 Redis 中你也见过这个配置项,一个影响性能的关键配置项。它是指 MySQL 这个服务的全连接队列的大小。全连接队列的大小由两部分决定——listen 函数里的 backlog 以及 Linux 内核参数 /proc/sys/net/core/somaxconn,最终的队列大小由数字最小的那个来决定。我们在 Redis基础篇06 — 配置文件详解(一) 中说明过。
  • max-connections = 700 – MySQL 的最大连接数,范围为 [1,100000],值越大,占用的内存资源越多。该配置项也在 Redis 中见过,参阅 Redis基础篇07 — 配置文件详解(二)。请注意文件描述符的值,默认情况下,用户级别的文件描述符上限为 1024
  • sync-binlog = 1 – 控制数据库的 binlog 间隔多少秒刷新到磁盘上去
  • innodb-buffer-pool-size = 1G – innodb 缓冲池大小,通常为当前可用内存的 80%
  • read-only = 0 – 是否只读,0 值表示当前数据库实例可读可写。
  • binlog-format = ROW – binlog 的格式

最后,我们需要修改初始的 root 密码:

Shell > /usr/local/mysql/bin/mysqld_safe  --user=mysql & 
Shell > /usr/local/mysql/bin/mysql -u root --password="wl%J,b)cM6-y";

Mysql > ALTER USER 'root'@'localhost' IDENTIFIED BY '338922549'; 
笔记
MySQL 8 为了安全性考虑,默认不允许 root 通过远程登录。

10.1.1.4/24 安装和配置 MySQL

步骤同上,但是 /etc/my.cnf 稍有不同:

[client]
port = 3306
socket = /tmp/mysql.sock

[mysqld]
server-id = 2  ← 不同项
port = 3306
socket = /tmp/mysql.sock
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
user = mysql
log-error = /usr/local/mysql/data/mysqld_start.err
bind-address = *
default-storage-engine = INNODB
group-concat-max-len = 102400
skip-name-resolve
back-log = 151
max-connections = 700
wait-timeout = 90
max-allowed-packet = 100M
read-buffer-size = 512K
sync-binlog = 1
innodb-buffer-pool-size = 1G
relay-log = /usr/local/mysql/data/replica-relaylog  ← 开启中继日志,不同项
replicate-ignore-db = mysql  ← 复制时要忽略的 source server 的库,可以填写多行。不同项
replicate-ignore-db = sys 
replicate-ignore-db = performance_schema 
replicate-ignore-db = information_schema

[mysqldump]
quick

修改 root 的初始密码:

Shell > /usr/local/mysql/bin/mysql -u root --password="lOt;USseu8qh";

Mysql > ALTER USER 'root'@'localhost' IDENTIFIED BY '95270110'; 

主从复制的操作步骤

步骤1:在 10.1.1.3/24 上创建用于复制的用户

Mysql > create user  'mysqlsync'@'%'  identified  by  '1592778'; 

Mysql > grant  replication slave on  *.*  to 'mysqlsync'@'%';

 # 一定要执行这一步,如果不执行,在从服务器上 使用 show slave status\G; 报错,提示——Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connectio
Mysql > alter user 'mysqlsync'@'%' identified with mysql_native_password by '1592778'; 

Mysql > show grants for 'mysqlsync'@'%';

# 查看使用到的 binlog 
Mysql> show master status;
+----------------------+----------+--------------+------------------+-------------------+
| File                 | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------------+----------+--------------+------------------+-------------------+
| source-binlog.000002 |      986 |              |                  |                   |
+----------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

步骤2:在 10.1.1.4/24 上执行复制操作

Mysql > change replication source to 
source_host='10.1.1.3',
source_user='mysqlsync',
source_password='1592778',
source_log_file='source-binlog.000002',
source_log_pos=986;

# 如果这一步报错,可使用 reset replica;
Mysql > start replica;   

Mysql > show replica status\G;
# 或者
Mysql > show slave status\G;
...
Replica_IO_Running: Yes                                                                                                                                                  
Replica_SQL_Running: Yes   
...
...
Slave_IO_Running: Yes                                                                                                                                                  
Slave_SQL_Running: Yes
...

请注意!我们这里的主从同步是单向的,只有主从同步成功的那一刻起,新创建的库与表才会被同步,过往历史的并不会。当然,你可以将主服务器上的过往历史数据使用逻辑备份备份出来,并将它们恢复到从服务器中。

keepalived 的安装与配置

10.1.1.3/24 执行的操作

# 依赖包 
Shell > dnf -y install  wget make gcc openssl openssl-devel   libnl3-devel libnl3  tar  bzip2 gzip zip  xz

# 源代码编译
Shell > wget -c https://keepalived.org/software/keepalived-2.2.7.tar.gz &&  tar -zvxf keepalived-2.2.7.tar.gz  -C  /usr/local/src/ 

Shell > cd /usr/local/src/keepalived-2.2.7/  && ./configure --prefix=/usr/local/keepalived \
--with-init=systemd  \
--with-systemdsystemunitdir=/usr/lib/systemd/system \
&& make && make install 

配置 Keepalived:

Shell > cd  /usr/local/keepalived/etc/keepalived && mv keepalived.conf.sample keepalived.conf

Shell > vim /usr/local/keepalived/etc/keepalived/keepalived.conf
global_defs {
   router_id VRRP01
   vrrp_skip_check_adv_addr
   enable_script_security
   script_user root
}

vrrp_script check_mysql {
    script "/usr/local/keepalived/check_mysql.sh"
    interval 2
    weight -5
}

vrrp_instance VI_1 {
    state MASTER
    interface ens160
    virtual_router_id 51
    priority 100
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.1.1.15/24  dev  ens160  label ens160:1
    }

    track_script {
        check_mysql
    }
}

Shell > vim /usr/local/keepalived/check_mysql.sh
#!/bin/bash
port=$(ss -tulnp | grep mysqld | awk '{print $5}' | cut -f 2 -d ":" | grep -w 3306)

if [ -z "${port}" ]
    then
    systemctl stop keepalived.service

fi

Shell > chmod 755 /usr/local/keepalived/check_mysql.sh

Shell > vim /usr/lib/systemd/system/keepalived.service
...
[Service] 
...
ExecStart=/usr/local/keepalived/sbin/keepalived -f /usr/local/keepalived/etc/keepalived/keepalived.conf
...   

10.1.1.4/24 执行的操作

安装步骤同上。

配置 Keepalived:

Shell > cd  /usr/local/keepalived/etc/keepalived && mv keepalived.conf.sample keepalived.conf

Shell > vim /usr/local/keepalived/etc/keepalived/keepalived.conf
global_defs {
   router_id VRRP02
   vrrp_skip_check_adv_addr
   enable_script_security
   script_user root
}

vrrp_script check_mysql {
    script "/usr/local/keepalived/check_mysql.sh"
    interval 2
    weight -5
}

vrrp_instance VI_1 {
    state BACKUP
    interface ens160
    virtual_router_id 51
    priority 50
    advert_int 1
    authentication {
        auth_type PASS
        auth_pass 1111
    }
    virtual_ipaddress {
        10.1.1.15/24  dev  ens160  label  ens160:1
    }

    track_script {
        check_mysql
    }
}

Shell > vim /usr/local/keepalived/check_mysql.sh
#!/bin/bash
port=$(ss -tulnp | grep mysqld | awk '{print $5}' | cut -f 2 -d ":" | grep -w 3306)

if [ -z "${port}" ]
    then
    systemctl stop keepalived.service

fi

Shell > chmod 755 /usr/local/keepalived/check_mysql.sh

Shell > vim /usr/lib/systemd/system/keepalived.service
...
[Service] 
...
ExecStart=/usr/local/keepalived/sbin/keepalived -f /usr/local/keepalived/etc/keepalived/keepalived.conf   
...  

注意点:

  • Master 和 Backup 的 router_id 必须不同且唯一
  • VRRP 实例名称必须相同,这里都是 VI_1
  • VRRP 实例里的 VRID 必须相同,这里都是 51
  • Master 的优先级要比 Backup 的优先级高50
  • 若在配置文件未写入任何有关抢占模式方面的内容,则默认就是 抢占模式

模拟主备切换

前文提到,MySQL 8 为了安全性考虑,默认不允许 root 登录,因此需要创建相关的登录用户。

前面的配置文件提到,我忽略了 mysql、sys、performance_schema、information_schema 这四个库的复制。在实际情况下,您在 source 和 replica 所创建的用户与密码应该相同,这里只是为了具体演示出效果与差异。

# 10.1.1.3/24
Mysql > create user  'mclient1'@'%'  identified  by  'google404'; 
Mysql > grant all  privileges on  *.*  to 'mclient1'@'%';

# 10.1.1.4/24
Mysql > create user  'bclient1'@'%'  identified  by  'googlecloud'; 
Mysql > grant all  privileges on  *.*  to 'bclient1'@'%';

在正常情况下,客户端可通过 VIP 进行访问:

若假设 Source MySQL 故障了(相当于 Master Keepalived 故障),手动停止 —— /usr/local/mysql/bin/mysqladmin -u root -p shutdown

此时 Backup keepalived的日志输出如下:

4月 23 13:21:48 Backup Keepalived_vrrp[18146]: (VI_1) Backup received priority 0 advertisement
4月 23 13:21:49 Backup Keepalived_vrrp[18146]: (VI_1) Receive advertisement timeout
4月 23 13:21:49 Backup Keepalived_vrrp[18146]: (VI_1) Entering MASTER STATE
4月 23 13:21:49 Backup Keepalived_vrrp[18146]: (VI_1) setting VIPs.
4月 23 13:21:49 Backup Keepalived_vrrp[18146]: (VI_1) Sending/queueing gratuitous ARPs on ens160 for 10.1.1.15
4月 23 13:21:49 Backup Keepalived_vrrp[18146]: Sending gratuitous ARP on ens160 for 10.1.1.15
4月 23 13:21:49 Backup Keepalived_vrrp[18146]: Sending gratuitous ARP on ens160 for 10.1.1.15
4月 23 13:21:49 Backup Keepalived_vrrp[18146]: Sending gratuitous ARP on ens160 for 10.1.1.15
4月 23 13:21:49 Backup Keepalived_vrrp[18146]: Sending gratuitous ARP on ens160 for 10.1.1.15
4月 23 13:21:49 Backup Keepalived_vrrp[18146]: Sending gratuitous ARP on ens160 for 10.1.1.15
4月 23 13:21:54 Backup Keepalived_vrrp[18146]: (VI_1) Sending/queueing gratuitous ARPs on ens160 for 10.1.1.15
4月 23 13:21:54 Backup Keepalived_vrrp[18146]: Sending gratuitous ARP on ens160 for 10.1.1.15
4月 23 13:21:54 Backup Keepalived_vrrp[18146]: Sending gratuitous ARP on ens160 for 10.1.1.15
4月 23 13:21:54 Backup Keepalived_vrrp[18146]: Sending gratuitous ARP on ens160 for 10.1.1.15
4月 23 13:21:54 Backup Keepalived_vrrp[18146]: Sending gratuitous ARP on ens160 for 10.1.1.15
4月 23 13:21:54 Backup Keepalived_vrrp[18146]: Sending gratuitous ARP on ens160 for 10.1.1.15

此时依旧可以正常访问:

Avatar photo

关于 陸風睿

GNU/Linux 从业者、开源爱好者、技术钻研者,撰写文档既是兴趣也是工作内容之一。Q - "281957576";WeChat - "jiulongxiaotianci"
用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇