一、mysql主从复制的思考
在高并发的时候,实现读写分离可以支撑更高的读并发的压力,在很多情况下,都是读多写少。针对于这种情况,可以写一个主库,主库下挂多几个从库,多个从库来进行读操作,从而减轻读并发的压力。那么问题来了,我们可能需要去想明白这三个问题:
- 如何实现Mysql读写分离?
- Mysql主从复制原理是啥?
- 如何解决Mysql主从同步的延时问题?
二、如何实现Mysql读写分离
大概思路就是实现数据库集群,其中一个是主库,负责写入数据,其他作为从库,负责读取数据。需要做到的目标就是:
- 读库和写库的数据一致(主从复制)
- 写数据必须写到写库
- 读数据必须到读库
可以有两种方案:应用层解决和中间件解决
2.1 应用层解决方案
应用层.png通过程序选择将sql语句请求到主库/从库,程序自动完成数据源间切换,不需要引用中间件,缺点是不能够动态的增加数据源。
中间件.png通过中间件可以动态的添加数据源而不用修改源程序。
三、Mysql主从复制原理
主库将变更写入 binlog 日志,然后从库连接到主库之后,从库有一个 IO 线程,将主库的 binlog 日志拷贝到自己本地,写入一个 relay 中继日志中。接着从库中有一个 SQL 线程会从中继日志读取 binlog,然后执行 binlog 日志中的内容,也就是在自己本地再次执行一遍 SQL,这样就可以保证自己跟主库的数据是一样的。
这里有一个非常重要的一点,就是从库同步主库数据的过程是串行化
的,也就是说主库上并行
的操作,在从库上会串行执行。所以这就是一个非常重要的点了,由于从库从主库拷贝日志以及串行执行 SQL 的特点,在高并发场景下,从库的数据一定会比主库慢一些,是有延时的
。所以经常出现,刚写入主库的数据可能是读不到的,要过几十毫秒,甚至几百毫秒才能读取到。
而且这里还有另外一个问题,就是如果主库突然宕机,然后恰好数据还没同步到从库,那么有些数据可能在从库上是没有的,有些数据可能就丢失了。
所以 MySQL 实际上在这一块有两个机制,一个是半同步复制
,用来解决主库数据丢失问题;一个是并行复制
,用来解决主从同步延时问题。
这个所谓半同步复制,也叫 semi-sync 复制,指的就是主库写入 binlog 日志之后,就会将强制此时立即将数据同步到从库,从库将日志写入自己本地的 relay log 之后,接着会返回一个 ack 给主库,主库接收到至少一个从库的 ack 之后才会认为写操作完成了。
所谓并行复制,指的是从库开启多个线程,并行读取 relay log 中不同库的日志,然后并行重放不同库的日志,这是库级别的并行。
四、如何解决Mysql主从同步延迟问题
判断主从延迟的方法:
在从数据库中,通过指令:show slave status\G
查看输出的Seconds_Behind_Master参数的值来判断,是否有发生主从延时。
NULL - 表示io_thread或是sql_thread有任何一个发生故障,也就是该线程的Running状态是No,而非Yes.
0 - 该值为零,是我们极为渴望看到的情况,表示主从复制良好,可以认为lag不存在。
正值 - 表示主从已经出现延时,数字越大表示从库落后主库越多。
负值 - 几乎很少见,只是听一些资深的DBA说见过,其实,这是一个BUG值,该参数是不支持负值的,也就是不应该出现。
解决方案:
当主库的TPS并发较高时,产生的DDL数量超过slave一个sql线程所能承受的范围,那么延时就产生了,当然还有就是可能与slave的大型query语句产生了锁等待。
所以可以有两种方案,将高并发的主库拆分成多个主库减少主库的并发量。
sql线程 采用 RelayLog 按库并行。
五、配置Mysql主从复制
上面讲了那么多的理论,是时候来捋起袖子实操。首先,开始配置Mysql主从复制。
5.1 配置环境
使用虚拟机开启两台服务器192.168.180.128(主) 和192.168.180.130(从)
本地机子作为客户机(192.168.180.01)发送请求
5.2 Mysql主从配置
5.2.1 配置master数据库
cd /etc/mysql/mysql.conf.d
sudo vim mysqld.cnf
在【mysqld】中增加这几行
server_id = 11
log_bin=master_bin
log_slave_updates=true
重启mysql服务
sudo service mysql restart
进入mysql
sudo mysql -uroot -p
create user u_replication identified by '123456';
grant replication slave on *.* to 'u_replication'@'%'
flush privileges;
show master status
image.png
这个信息待会需要用到。
5.2.2 配置从数据库
cd /etc/mysql/mysql.conf.d
sudo vim mysqld.cnf
在【mysqld】中增加这几行
server_id = 22 //从服务器编号
relay_log=relay-log-bin //指定从服务器的中继日志
relay_log_index=slave-relay-bin.index //定义中级日志的位置和名称
重启mysql服务
sudo service mysql restart
进入从数据库授权
进入mysql
sudo mysql -uroot -p
change master to master_host='192.168.180.128',master_user='u_replication',master_password='123456',master_log_file='master_bin.000025',master_log_pos=154;
flush privileges;
start slave;
show slave status \G
截图两个slave_io_running YES 和 slave_sql_running Yes 则表示成功。
网友评论