为什么要设计mysql主从复制架构
为了解决mysql中出现单点故障的问题,进而设计了mysql主从架构,保障整体服务性能和稳定。mysql提供的复制也是一种高性能高可用方案,实现最终一致性。而且主从架构的设计,往往是一主库,一从库,主从库之间异步同步数据。可以让主服务器写,让从服务器读,这样可以实现读写分离。
主从复制原理
- master将数据更改记录到二进制日志binlog。
- slave将主服务器的二进制日志复制到自己的中继日志relay log。
- 服务器重做中继日志中的日志,把更改应用到自己的数据库,达到数据最终一致性。
docker-compose搭建主从复制架构
镜像名称 | 内外端口 | 容器名称 |
---|---|---|
mysql:8.0.29 | 3389:3306 | mysql-master |
mysql:8.0.29 | 3379:3306 | mysql-slave |
- 编写docker-compose文件:
version: "3"
services:
mysql-master:
image: mysql:8.0.29
ports:
- 3389:3306
volumes:
- /home/mysql/master-slave/master/conf/:/etc/mysql/conf.d
- /home/mysql/master-slave/master/data/:/var/lib/mysql
- /home/mysql/master-slave/master/log/:/var/log/mysql
environment:
MYSQL_ROOT_PASSWORD: spy1679358426
MYSQL_DATABASE: sunpy-mysql
MYSQL_USER: sunpy
MYSQL_PASSWORD: spy1679358426
restart: always
container_name: mysql-master
mysql-slave:
image: mysql:8.0.29
ports:
- 3379:3306
volumes:
- /home/mysql/master-slave/slave/conf/:/etc/mysql/conf.d
- /home/mysql/master-slave/slave/data/:/var/lib/mysql
- /home/mysql/master-slave/slave/log/:/var/log/mysql
environment:
MYSQL_ROOT_PASSWORD: spy1679358426
MYSQL_DATABASE: sunpy-mysql
MYSQL_USER: sunpy
MYSQL_PASSWORD: spy1679358426
restart: always
container_name: mysql-slave
- 启动mysql编排容器:
docker-compose -f mysql.yml up -d
- 配置my.cnf文件:
这部分在我们的外部conf目录下配置就行了,因为我们挂载了外部文件夹。
主:
[mysqld]
server-id=1
log-bin=mysql-bin
binlog_format=MIXED
max_binlog_size = 124M
expire_logs_days = 3
binlog_ignore_db = mysql,performance_schema,information_schema,sys
从:
[mysqld]
server_id = 2
log_bin = mysql-bin
binlog_format=MIXED
max_binlog_size = 124M
expire_logs_days = 3
replicate-ignore-db=mysql,performance_schema,information_schema,sys
relay_log_recovery = 1
log_slave_updates = 1
- 查看主从状态:
mysql> show master status;
+------------------+----------+--------------+-------------------------------------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+-------------------------------------------------+-------------------+
| mysql-bin.000068 | 157 | | mysql,performance_schema,information_schema,sys | |
+------------------+----------+--------------+-------------------------------------------------+-------------------+
1 row in set (2.33 sec)
- change命令同步主从数据
change master to
master_host='xxx.xx.xxx.xxx',
master_user='root',
master_password='xxxxx',
master_port=3389,
master_log_file='mysql-bin.000068',
master_log_pos= 0,
master_connect_retry=30;
- 开启从库
mysql> start slave;
Query OK, 0 rows affected (0.44 sec)
查看是否开启:
验证:
master库新增一条记录,slave库也会新增一条记录。
问题思考:主从复制延迟
思考:在测试的时候发现,主从复制并不是很快的,不会马上同步数据。
问题:如果我们采取读写分离方式,那么主库数据写了一条记录。如果我们写完后,再从库去刷新数据列表记录,会发现记录还未同步过来。这种实时性要求比较高的时候该怎么办?
- 第一种方案(消息队列替代从库查询):
插入数据向消息队列生产消息的时候,将消息全部内容直接同步到消费者,消费者直接从消息队列获取消息,不用再重新查询从库了。 - 第二种方案(存放到缓存):
消费者直接从缓存查询,不查询从库了。注意:缓存与数据库可能存在数据不一致的情况 - 第三种方案:
直接查主库,那么主从复制也没啥意义了。
问题思考:主从库数据不一致
思考:主库新增数据成功,然后主库数据通过binlog同步的时候,发现binlog无法同步,造成主从库结果不一致。
答:
GTID方案,就是主库生成一个GTID标识,同当前记录一同写入到binlog中。从库将binlog日志写入到relay-log中。从relay-log中获取GTID,通过GTID获取从库中的binlog,如果有记录,说明GTID事务已执行。没有记录,那么从库会从 relay-log 中执行该 GTID 的事务,并记录到 binlog 中。
mysql开启GTID:
[mysqld]
# 启用GTID
gtid-mode=on
# 强制GTID的一致性
enforce-gtid-consistency=true
# slave更新是否记入日志(1表示记入、0表示不记入)
log-slave-updates=1
参考:
https://blog.csdn.net/JohnnyG2000/article/details/124701214
网友评论