mysql主从架构
docker实现mysql节点
概述:该文档以本地方式搭建mysql主从集群,因资源有限故采用docker容器化方式搭建。下面是mysql容器生成的具体命令。
-
生成两个mysql容器,分别对应不同的端口:3307、3308
容器一:3307 docker run --name mysql3307_RS -p 3307:3306 --privileged=true -ti -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=play -v /home/mysql/docker-data/3307/conf:/etc/mysql/conf.d -v /home/mysql/docker-data/3307/data/:/var/lib/mysql -v /home/mysql/docker-data/3307/logs/:/var/log/mysql -d mysql:5.7
容器二:3308 docker run --name mysql3308_RS -p 3308:3306 --privileged=true -ti -e MYSQL_ROOT_PASSWORD=123456 -e MYSQL_DATABASE=play -v /home/mysql/docker-data/3308/conf:/etc/mysql/conf.d -v /home/mysql/docker-data/3308/data/:/var/lib/mysql -v /home/mysql/docker-data/3308/logs/:/var/log/mysql -d mysql:5.7
命令解释:
conf:mysql配置文件目录。后面就是在这个文件夹下进行配置。
data:mysql数据存放路径。innodb、MyISAM等各种存储引擎的具体数据记录,relaylog、binlog等日志文件都是在这个路径下以磁盘形式存在的。
logs:mysql的日志文件路径。命令中就是将此三个目录挂载到了宿主机上,以方便修改配置文件、查看日志文件。
这里选择的是mysql的5.7版本。 -
容器此时已经启动了,可以通过mysql-client命令连接到这两个mysql数据库服务上了。
# 连接容器一的mysql服务: mysql -hlocalhost -P3307 -uroot -p123456 # 连接容器二的mysql服务: mysql -hlocalhost -P3308 -uroot -p123456
异步复制配置:
概述:主从复制Replication架构是一种可靠性较高的mysql集群架构。可靠性往往达到99%以上。多用于mysql主从热备、读写分离等使用场景。主从架构也是MySQL Replication结构多种变换的最基础的架构,其他Replication架构的变形都是以它为基础原理演变的。
配置:
-
主节点3307配置路径:/home/mysql/docker-data/3307/conf/my.cnf
[mysqld] # server-id 在集群中必须唯一,该id在日志打印中可见用来指明集群中节点 server-id=111 # 开启复制功能,“mysql-bin” 即就是binlog日志的文件名前缀 log-bin=mysql-bin auto_increment_increment=2 auto_increment_offset=1 lower_case_table_names=1
-
从节点3308配置路径:/home/mysql/docker-data/3308/conf/my.cnf
[mysqld] server-id=112 log-bin=mysql-bin auto-increment-increment=2 auto-increment-offset=2
开启异步复制:
- 主3307添加权限:
GRANT REPLICATION SLAVE,FILE,REPLICATION CLIENT ON *.* TO 'repluser'@'%' IDENTIFIED BY '123456'; FLUSH PRIVILEGES; # 给slave从节点添加一个复制客户端权限
- 查看主3307节点到从节点的复制起点:
show master STATUS; # 命令结果File、Position所表示的就是从节点的复制起点
- 从3308节点配置其主节点、复制起点:
# 其主节点:选取主3307容器的IP地址,端口3306不是3307 # 用户repluser为主3307授权的从客户端账号 # file和pos分别对应3步骤中的File、Position change master to master_host='172.17.0.4',master_port=3306,master_user='repluser',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=154;
- 从3308启动slave模式:
到此为止,mysql主从架构搭建完成,可以在主3307节点添加数据,看到从3308节点就会同步到数据。start slave; #这个命令即就是开启从3308节点的IO、SQL进程。此两个进程可以通过执行show processlist; 命令查看到
注意:从3308节点也可以添加表、数据,但是不会被同步到主3307。但从3308的数据添加不会影响主3307后续的数据添加的同步。show global variables like “%log%”;
可以通过如上命令查看主、从节点的二进制日志是否开启。
如何查看log日志
查看日志,即就是查看 /home/mysql/docker-data/3307/data/
和 /home/mysql/docker-data/3308/data/
两个路径下的日志文件。
- 主3307查看:
mysql-bin.index文件:存着所有binlog当前的日志文件名,最后一行是最新的binlog日志文件。 再根据mysql-bin.index所提供的日志文件名可查看具体的binlog文件 我这里mysql-bin.index文件存的就是mysql-bin.000001。说明目前只有一个binlog日志文件就是mysql-bin.000001文件的。
- 从3308查看:
93920de6d488-relay-bin.index 文件(前缀字符串是容器id):里面放着所有的relaylog日志文件,最后一行是最新的relaylog文件。
异步复制优缺点:
- 优点:
master节点不需要等待slave节点同步,速度快,直接进行数据库存储引擎级别的数据提交commit操作。 - 缺点:
因为不需要等待,对于binlog的改变系统级别的监听,没有可靠的同步到slave节点的可靠性保证。
从节点宕机启动
提供两种宕机演示:
第一种:从3308的IO线程挂掉:
- kill掉IO进程:stop slave io_thread;
结果: - 主3307数据改动
- 启动IO进程:start slave io_thread;
结果:
最终可以看到,从3308在IO进程恢复后,又同步主3307更改的数据完成。
第二种:从3308的mysql服务宕机:
-
进入容器执行命令:mysqladmin shutdown -p123456。即可关闭从节点mysql服务。
-
更改主3307数据后再启动,同样的,从3308的数据同步也是完成的。
进入容器命令:docker start mysql3308_RS
半同步复制
概述:半同步复制提供两种模式:AFTER_SYNC、AFTER_COMMIT。根据同步等待的时机点不同来区分。故所提供的可靠性保证也不同。
mysql默认使用第一种AFTER_SYNC,也是可靠性更高的模式。
默认不是半同步复制,是以插件形式提供的。
整个的配置都是手动命令方式的,配置文件配置方式这里不推荐使用。
配置:
尽量按照先从再主的顺序进行。
- 分别安装插件:
#从3308上安装 install plugin rpl_semi_sync_slave soname 'semisync_slave.so'; # 主3307上安装 install plugin rpl_semi_sync_master soname 'semisync_master.so';
- 分别查看插件是否安装成功:
show plugins;
- 开启半同步复制:
1. 从3308: 先停止slave的进程,开启半同步复制,再开启进程: stop slave; set global rpl_semi_sync_slave_enabled = 1; start slave; 2. 主3307 开启半同步,设置半同步等待时间: set global rpl_semi_sync_master_enabled = 1; set global rpl_semi_sync_master_timeout = 10000;
至此,半同步复制已开启,可以使用一下命令查看主、从的开启状态、相关参数设置。
show global status like “%sync%”; #状态
show global VARIABLES like “%sync%”; #相关参数
异常宕机
半同步复制下,与同步复制相同,在从节点恢复后都会及时的同步主节点的数据。
但半同步复制在从节点宕机后,会进行默认10s等待,在等待到从节点的ACK返回时会唤醒engine存储引擎提交数据。若10s未收到从节点的ACK,还是会提交的,只是会等待10s。这样很大概率上减少了主从不一致的概率。
两种模式区别:
建议使用第一种,AFTER_SYNC。
异步复制 vs 半同步复制:
异步复制:只是master节点对binlog文件的变化有系统级别的监听,master节点本身不需要对binlog同步到slave的精确性、及时性提供有效保证机制。
半同步复制:master在异步复制监听binlog文件编号的基础上多了对同步到slave提供了更完善的保证机制,进行一定的等待时间在slave返回ACK后master节点才被唤醒继续向下执行。
Replication架构的各种演变:
- 一主多从
- 双主
- 主从级联
- 双主级联
Q & A
- 从节点如何更新主节点的IP、port、position等配置:
1. stop slave; //停止slave的IO、SQL进程 2. 重新执行如下命令: change master to master_host='<IP>',master_port=<port>,master_user='repluser',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=<pos>;
- 主从DB如何处理insert的主键冲突问题?
在配置文件中设置: auto_increment_increment=2。#id步长 auto_increment_offset=1 #起始id 每个mysql节点的起始id不同,步长相同,则在数据添加过程中,避免了主键冲突的情况出现。
- 在实际分布式环境下,主键如何实现?
1. 在高并发模式下,多采用UUID 或者 雪花算法来实现分布式的主键生成。不建议使用mysql本身自增主键。 2. 批量预取:从第三方组件去一次获取一个连续序列的id进行预留使用,性能较好。 3. 数据库中间件支持多种分布式下的id获取:机器ID + 时间戳等 4. 在并发程度不高,可以使用mysql自增主键,但要开启主键自增锁,防止并发冲突数据被覆盖。
- after_commit的缺点?
1. 幻读 2. 数据丢失
- 为什么不建议DB启动时就开启半同步复制?
因为半同步复制有10s的等待时间,如果从节点从一个比较早的起始点开始同步主节点数据,会因为事务提交较多和网络问题拖死主节点,最终导致主节点无法对外提供服务。
- start slave作用是什么?stop slave??
开启从节点的两个用于主从复制的重要进程:IO进程、SQL进程 IO进程:用于写入relaylog文件 SQL进程:实现SQL在从节点的重做 可通过 stop slave; # 关闭这两个进程 stop slave io_thread; # 仅关闭IO进程
- 为什么使用半同步复制?
半同步复制提供了可靠的机制,确保数据可靠的同步到从节点。大大地降低了主从数据的不一致概率。