目录
读写分离很好的解决了主服务器的性能问题,可以让主服务器专注写数据,将读数据的操作压力分摊到各个从服务器上。同时多个MySQL服务器的同时运行,提高了集群的容错性。即使主服务器宕机,也能很快选出新的leader,减小了服务器宕机带来的损失。而读写分离需要主从复制来保证数据的一致性。(通过缓存来解决)
一、主从复制常见架构
常规复制架构
一台master对应多台slave。master负责写,slave负责读。该方案因为只有一台服务器负责写数据,master宕机后,在重新选主的这段时间内整个服务将无法完成写的操作,影响性能;同时如果master还有数据没有完成同步,就会有数据丢失的问题。
双主复制架构
整个集群是两个master,一台负责读一台负责写,数据相互复制,这样会避免数据丢失的问题,但因为只有两台服务器,对性能的提升是有限的。
双主复制架构优化
整个集群是两个master和若干个slave的集合,两台master负责写数据并相互复制,同时将数据复制给slave。在DML操作频繁的系统中需要应用到该架构逻辑。
级联复制架构
级联复制架构是对常规复制架构的优化。因为常规复制架构如果slave过多,虽然读操作的压力小了,但对master来说它需要对所有的slave进行复制操作,增加了他的I/O压力。而级联复制架构对slave进行分级,master只需要对有限个slave复制,再通过这几个一级slave对剩下的二级slave进行复制操作,极大减轻了master的压力。
但这也造成了一个问题:分级的存在,延缓了数据同步的速度。如果用户在写入数据后立刻读取数据,就无法保证数据的一致性。
二、主从复制流程
master---线程:dump thread;日志:bin log
slave---线程:IO thread,SQL thread;日志:relay log
流程
①请求写入master的bin log;
②master监听到bin log变化后启动dump thread;
③dump thread通知slave的IO thread并获取对应slave的bin log和pos信息;
④dump thread根据获取到的信息将对应的日志内容同步给slave;
⑤IO thread将日志写入relay log,同时返回master一个ACK(成功应答)信息;
⑥SQL thread根据relay log的变动来执行数据库的同步。
三、主从复制分类
异步复制(默认)
master会在①执行结束后立刻返回用户数据信息,不关心后面操作的成功与否。因此如果出现同步不成功等问题,master也无法做出有效的判断。
半同步复制
master会在①执行结束后sleep,直到⑤收到ACK信息后被唤醒,返回用户数据信息。master会有一个最大sleep时间,超过这个时间会自动唤醒,记录slave状态的同时将复制模式临时转化为异步复制,返回用户数据信息。
四、主从复制操作
我是在docker中进行主从复制的测试。
①在docker中创建三个端口号不同的mysql容器(通过数据卷挂载将容器的数据持久化)
docker run -d -p 3306:3306 --name mysql01 --privileged=true -e MYSQL_ROOT_PASSWORD="password" -e MYSQL_USER="LZL" -e MYSQL_PASSWORD="pwd123" -v=/docker/mysql/config/my.cnf:/etc/my.cnf -v=/docker/mysql/data:/var/lib/mysql mysql/mysql-server
②修改mysql的配置文件my.cnf
(因为docker内多个mysql间网络通讯有问题,转去学习docker,之后再来填坑)
master
[mysqld]
user=mysql
skip-name-resolve //禁用dns解析server-id=1
log-bin=mysql-binauto_increment_increment=2 //自增的步长
auto_increment_offset=1 //id从1开始
slave
[mysqld]
user=mysql
skip-name-resolveserver-id=2
log-bin=mysql-bin
auto_increment_increment=2
auto_increment_offset=1
PS:auto_increment_increment和auto_increment_offset两个属性非必须,常用于双主复制架构
PS:修改my.cnf文件后需要重启一下docker的mysql服务---docker restart mysql_test1
③设置主从服务器的相关配置
master
grant replication slave,file,replication client on *.* to 'user'@'%' inentified by '111111'; //赋予user该用户复制数据的权限
flush privileges; //刷新用户权限(每次更改权限都需要刷新)
show master status;
slave
change master to master_host='172.17.253.195',master_user='user',master_password='111111',master_log_file='mysql-bin.000001',master_log_pos=7197;
start slave;
show slave status\G
Slave_IO_Running和Slave_SQL_Running都显示Yes表示配置成功。
五、主从复制遇到的坑
①docker内各mysql容器无法通讯
在设置slave的时候Slave_IO_Running一直显示No,Last_IO_Errno提示2003,即slave无法和master服务器连接。一路摸排各种问题后发现是访问的ip错了。一开始我访问的ip是通过"docker inspect mysql_test1"获取的,该ip是宿主机和容器通讯的时候用的,容器间相互通讯应该用宿主机对内的ip?(留个坑,要重新学计网了)
②配置好后主从复制没有实现
我的master服务器一开始有数据,slave服务器是空的。在这种情况下原有表上的操作影响不到slave,如果进行表或者数据库的删除操作slave还会报错,Slave_SQL_Running变为No。因此在主从复制前需要将master的数据dump到slave中(转储SQL文件)。