美文网首页数据库相关MySQL
mysql主从复制与读写分离

mysql主从复制与读写分离

作者: 大炮对着虫子 | 来源:发表于2019-03-14 16:53 被阅读139次
    一、mysql主从复制的思考

    在高并发的时候,实现读写分离可以支撑更高的读并发的压力,在很多情况下,都是读多写少。针对于这种情况,可以写一个主库,主库下挂多几个从库,多个从库来进行读操作,从而减轻读并发的压力。那么问题来了,我们可能需要去想明白这三个问题:

    1. 如何实现Mysql读写分离?
    2. Mysql主从复制原理是啥?
    3. 如何解决Mysql主从同步的延时问题?
    二、如何实现Mysql读写分离

    大概思路就是实现数据库集群,其中一个是主库,负责写入数据,其他作为从库,负责读取数据。需要做到的目标就是:

    1. 读库和写库的数据一致(主从复制)
    2. 写数据必须写到写库
    3. 读数据必须到读库

    可以有两种方案:应用层解决和中间件解决

    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 则表示成功。

    相关文章

      网友评论

        本文标题:mysql主从复制与读写分离

        本文链接:https://www.haomeiwen.com/subject/sfxqmqtx.html