MySQL 搭建双主复制服务并通过 HAProxy 负载均衡

在数据库管理中,数据的备份和同步是至关重要的环节,而双主复制(Dual Master Replication)作为一种高可用性和数据同步的解决方案,本文将介绍MySQL双主复制的配置过程并通过 HAProxy 负载均衡,感兴趣的朋友一起看看吧

MySQL 搭建双主复制高可用服务

在数据库管理中,数据的备份和同步是至关重要的环节,而双主复制(Dual Master Replication)作为一种高可用性和数据同步的解决方案,通过让两个数据库实例同时充当主服务器和从服务器,MySQL双主复制可以实现数据的双向同步,为数据库系统提供了更灵活和可靠的解决方案。即使其中一个主服务器发生故障,另一个主服务器仍然可以继续提供服务,确保系统的稳定性和可用性。这种数据同步方式不仅可以加强数据的备份与恢复能力,还可以提高系统的扩展性,适用于需要高度数据一致性和容错性的场景。

本文将介绍MySQL双主复制的配置过程,整体实现架构如下:

主机规划:

ip 规划
192.168.73.101 Mysql-1
192.168.73.102 Mysql-2
192.168.73.103 Haproxy

二、MySQL-1 部署

mysql 的部署这里采用 docker + docker-compose 的方式快速实现,主要关注点在于配置文件:

首先编写 my.cnf 文件,写入如下内容:

yml 复制代码
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql
secure-file-priv= NULL
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# 主从同步
server-id = 1
log-bin = mysql-bin
sync_binlog = 1
binlog_checksum = none
binlog_format = mixed
auto-increment-increment = 2
auto-increment-offset = 1
slave-skip-errors = all
event_scheduler = 1
max_allowed_packet = 64M
# Custom config should go here
!includedir /etc/mysql/conf.d/

其中主从复制的参数解释如下:

server-id = 1:指定MySQL实例的唯一标识ID,用于在主从复制中区分不同的MySQL实例。

log-bin = mysql-bin:启用binlog日志,并指定binlog文件的前缀名为mysql-bin。binlog用于记录所有的数据更改操作,以便主从服务器之间进行数据同步。

sync_binlog = 1:表示每次事务提交时都将强制把binlog缓冲区的内容写入磁盘,确保binlog日志及时持久化,提高数据安全性。

binlog_checksum = none:设置binlog文件的校验方式为none,表示不对binlog文件进行校验和验证。

binlog_format = mixed:指定binlog日志的格式为mixed,即混合模式,根据具体情况自动选择使用statement或row格式记录数据变更。

auto-increment-increment = 2:设置自增长字段的增量值为2,用于在主从复制中避免自增字段冲突。

auto-increment-offset = 1:设置自增长字段的偏移量为1,用于在主从复制中避免自增字段冲突。

slave-skip-errors = all:当从服务器在执行SQL线程时发生错误时,跳过所有错误继续执行,这可能会导致数据不一致,谨慎使用。

event_scheduler = 1:启用Event Scheduler,用于执行预定的事件任务。

max_allowed_packet = 64M:设置最大允许的数据包大小为64MB,用于控制单个数据库请求或查询的数据包大小限制。

编写 docker-compose.yml 文件:

yml 复制代码
version: '2.0'
services:         
  mysql:
    restart: always
    image: mysql:8.0.20
    container_name: mysql
    volumes:
      - ./data:/var/lib/mysql
      - ./my.cnf:/etc/mysql/my.cnf
    command:
      --lower_case_table_names=1
      --character-set-server=utf8
      --sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=123456
      - TZ=Asia/Shanghai 

启动服务:

js 复制代码
docker-compose up -d

客户端工具连接该数据库:

![image.png](p1-juejin.byteimg.com/tos-cn-i-k3...

查看当前 master 状态:

js 复制代码
show master status;

注意这里查询出来的 FilePosition 下面主从复制时会用到。

创建用于主从复制的用户:

js 复制代码
CREATE USER 'replica'@'%' IDENTIFIED WITH mysql_native_password BY 'replica123';
GRANT REPLICATION SLAVE ON *.* TO 'replica'@'%';
FLUSH PRIVILEGES;

三、MySQL-2 部署

同样编写 my.cnf 文件,写入如下内容:

js 复制代码
[client]
default-character-set=utf8
[mysql]
default-character-set=utf8
[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql
secure-file-priv= NULL
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
# 主从同步
server-id = 2
log-bin = mysql-bin
sync_binlog = 1
binlog_checksum = none
binlog_format = mixed
auto-increment-increment = 2
auto-increment-offset = 2
slave-skip-errors = all
event_scheduler = 1
max_allowed_packet = 64M
# Custom config should go here
!includedir /etc/mysql/conf.d/

配置和MySQL-1差不多,主要注意 server-idauto-increment-offset 的区别。

编写 docker-compose.yml

js 复制代码
version: '2.0'
services:         
  mysql:
    restart: always
    image: mysql:8.0.20
    container_name: mysql
    volumes:
      - ./data:/var/lib/mysql
      - ./my.cnf:/etc/mysql/my.cnf
    command:
      --lower_case_table_names=1
      --character-set-server=utf8
      --sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
    ports:
      - "3306:3306"
    environment:
      - MYSQL_ROOT_PASSWORD=123456
      - TZ=Asia/Shanghai 

启动服务:

js 复制代码
docker-compose up -d

客户端工具连接该数据库:

查看当前 master 状态:

js 复制代码
show master status;

同样这里查询出来的 FilePosition 下面主从复制时会用到。 创建用于主从复制的用户:

js 复制代码
CREATE USER 'replica'@'%' IDENTIFIED WITH mysql_native_password BY 'replica123';
GRANT REPLICATION SLAVE ON *.* TO 'replica'@'%';
FLUSH PRIVILEGES;

四、配置主主复制

MySQL-1 同步 MySQL-2

MySQL-1 中执行 :

js 复制代码
change master to master_host='192.168.73.102',master_user='replica',master_password='replica123',master_log_file='mysql-bin.000003',master_log_pos=152;

注意:其中 master_log_filemaster_log_pos 是上面部署 MySQL 2show master status; 查询的结果。 启动同步进程:

js 复制代码
start slave;

查看同步状态:

js 复制代码
show slave status

看到 Slave_IO_RunningSlave_SQL_Running 都为 Yes 则表示启动成功。

MySQL-2 同步 MySQL-1

MySQL-2 中执行 :

js 复制代码
change master to master_host='192.168.73.101',master_user='replica',master_password='replica123',master_log_file='mysql-bin.000003',master_log_pos=811;

注意:其中 master_log_filemaster_log_pos 是上面部署 MySQL 2show master status; 查询的结果。

启动同步进程:

js 复制代码
start slave;

查看同步状态:

js 复制代码
show slave status

看到 Slave_IO_RunningSlave_SQL_Running 都为 Yes 则表示启动成功。

五、测试主主复制

首先在 MySQL1 中创建数据库 testdb:

1 create database testdb;

然后在 MySQL 2 中查看数据库:

1 show databases;

可以正常查到 MySQL 1 中创建的数据库。

然后在 MySQL 2 中创建测试表:

123456 use testdb;``create table `test` ( ``` ``` `id` ```int` `not` `null` `auto_increment, `````name``` varchar`(255) `default` `null`,` primary` `key` (`id`)\`\`\` ) engine=InnoDB default` ` charset=utf8mb4 ``collate``=utf8mb4_0900_ai_ci;`

接着在 MySQL 1 中查看表:

12 use testdb;``show tables;

可以正常看到 MySQL 2 创建的表。

然后在 MySQL 1 中写入一条测试数据:

1 insert into test(``name`` ) ``values``(``'小明'``);

然后到 MySQL 2 中查看表数据:

1 select * ``from test;

可以正常查到 MySQL 1 写入的数据。

六、配置 HAProxy 负载 MySQL 服务

经过上面测试已经证明主主复制功能正常,数据无论写在哪个数据库上都能同步给另外一台,下面通过 HAProxy 负载均衡代理 MySQL 1MySQL 2 ,对外提供统一的入口。

在103机器 下载 HAProxy

js 复制代码
yum install -y haproxy

覆盖修改 /etc/haproxy/haproxy.cfg 配制文件,注意修改 backend mysql-apiserver 下的两个 MySQLip

js 复制代码
cat > /etc/haproxy/haproxy.cfg << EOF
#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global
    # to have these messages end up in /var/log/haproxy.log you will
    # need to:
    # 1) configure syslog to accept network log events.  This is done
    #    by adding the '-r' option to the SYSLOGD_OPTIONS in
    #    /etc/sysconfig/syslog
    # 2) configure local2 events to go to the /var/log/haproxy.log
    #   file. A line like the following can be added to
    #   /etc/sysconfig/syslog
    #
    #    local2.*                       /var/log/haproxy.log
    #
    log         127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon 
    # turn on stats unix socket
    stats socket /var/lib/haproxy/stats
#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------  
defaults
    mode                    http
    log                     global
    option                  httplog
    option                  dontlognull
    option http-server-close
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          1m
    timeout http-keep-alive 10s
    timeout check           10s
    maxconn                 3000
#---------------------------------------------------------------------
# mysql apiserver frontend which proxys to the backends
#--------------------------------------------------------------------- 
frontend mysql-apiserver
    mode                 tcp
    bind                 *:3306
    option               tcplog
    default_backend      mysql-apiserver    
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend mysql-apiserver
    mode        tcp
    balance     roundrobin
    server      master1   192.168.73.101:3306 check
    server      master2   192.168.73.102:3306 check
#---------------------------------------------------------------------
# collection haproxy statistics message
#---------------------------------------------------------------------
listen stats
    bind                 *:1080
    stats auth           admin:awesomePassword
    stats refresh        5s
    stats realm          HAProxy\ Statistics
    stats uri            /admin?stats
EOF

启动haproxy

js 复制代码
systemctl start haproxy

设置开机自启:

js 复制代码
systemctl enable haproxy

查看启动状态:

js 复制代码
systemctl status haproxy

测试

通过 103 服务器连接 MySQL

查看前面创建的数据库、表、数据:

写入一条数据:

js 复制代码
insert into test(name) values("小红");

分别到 MySQL 1MySQL 2查询数据:

都可以查询到数据,到此 MySQL 搭建双主复制服务 并 通过 HAProxy 负载均衡就结束了。

相关推荐
NiNg_1_2342 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
Chrikk3 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*3 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue3 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man3 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
customer085 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
Yaml46 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
小码编匠7 小时前
一款 C# 编写的神经网络计算图框架
后端·神经网络·c#