美文网首页
Mysql主从模式

Mysql主从模式

作者: 小幸运Q | 来源:发表于2020-10-10 21:46 被阅读0次

    https://www.cnblogs.com/fengzheng/p/13401783.html
    https://juejin.im/entry/6844903458290532366


    主从配置一般都是和读写分离相结合,主服务器负责写数据,从服务器负责读数据,并保证主服务器的数据及时同步到从服务器。

    主从模式示意图

    主节点

    1、当主节点上进行 insert、update、delete 操作时,会按照时间先后顺序写入到 binlog 中;
    2、当从节点连接到主节点时,主节点会创建一个叫做 binlog dump 的线程;
    3、一个主节点有多少个从节点,就会创建多少个 binlog dump 线程;
    4、当主节点的 binlog 发生变化的时候,也就是进行了更改操作,binlog dump 线程就会通知从节点 (Push模式),并将相应的 binlog 内容发送给从节点;

    从节点

    当开启主从同步的时候,从节点会创建两个线程用来完成数据同步的工作。

    (1)I/O线程: 此线程连接到主节点,主节点上的 binlog dump 线程会将 binlog 的内容发送给此线程。此线程接收到 binlog 内容后,再将内容写入到本地的 relay log。

    (2)SQL线程: 该线程读取 I/O 线程写入的 relay log,并且根据 relay log 的内容对从数据库做对应的操作。


    理论上怎么实现从库和主库的数据一致性?

    1、异步复制
    主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从库上,如果此时,强行将从提升为主,可能导致“数据不一致”。早期MySQL(5.5以前)仅仅支持异步复制。
    2、半同步复制
    MySQL在5.5中引入了半同步复制,主库在应答客户端提交的事务前需要保证至少一个从库接收并写到relay log中,半同步复制通过rpl_semi_sync_master_wait_point参数来控制master在哪个环节接收 slave ack,master 接收到 ack 后返回状态给客户端,此参数一共有两个选项 AFTER_SYNC & AFTER_COMMIT。

    • AFTER_COMMIT
    image.png

    AFTER_COMMIT时,commitTrx的调用在engine层commit之后,即在等待Slave ACK时候,虽然没有返回当前客户端,但事务已经提交,其他客户端会读取到已提交事务。如果Slave端还没有读到该事务的events,同时主库发生了crash,然后切换到备库。那么就会出现数据不一致的问题。如果主库永远启动不了,那么实际上在主库已经成功提交的事务,在从库上是找不到的,也就是数据丢失了。

    PS:早在11年前后,阿里巴巴数据库就创新实现了在engine层commit之前等待Slave ACK的方式来解决此问题。

    3、全同步复制

    MySQL官方针对上述问题,在5.7.2引入了Loss-less Semi-Synchronous,在调用binlog sync之后,engine层commit之前等待Slave ACK。这样只有在确认Slave收到事务events后,事务才会提交。

    set rpl_semi_sync_master_wait_point=AFTER_SYNC
    
    SET GLOBAL rpl_semi_sync_master_wait_for_slave_count= N;
    // 应答多少个slave才commit
    
    • AFTER_SYNC: 官方推荐的方式

    客户端发出commit请求后,在主库上写入binlog并推送给slave,slave接收到binlog并写入relaylog,发送ACK确认已经接收binlog后,master在引擎层commit,客户端接收commit完成,此时其他会话才可以看见已提交的数据。

    故障分析:假设master在接收ACK确认时宕机,因为在引擎层并没有提交,HA切换到从库,因为binlog已经写入从库的relaylog,因此不会造成数据丢失。

    但是也不是万无一失,因为当主库在binlog flush并且binlog同步到了备库之后,binlog sync之前发生了abort,那么很明显这个事务在主库上是未提交成功的(由于abort之前binlog未sync完成,主库恢复后事务会被回滚掉),但由于从库已经收到了这些Binlog,并且执行成功,相当于在从库上多出了数据,从而可能造成“数据不一致”。

    image.png

    在after_sync模式下解决了after_commit模式带来的数据不一致的问题,因为主库没有提交事务。

    此外,MySQL半同步复制架构中,主库在等待备库ack时候,如果超时会退化为异步后,也可能导致“数据不一致”。(等待的时间以rpl_semi_sync_master_timeout参数为准,默认为10秒。)

    其他防丢失操作

    1. 在master上修改配置
    innodb_flush_log_at_trx_commit = 1
    sync_binlog = 1
    

    上述两个选项的作用是:保证每次事务提交后,都能实时刷新到磁盘中,尤其是确保每次事务对应的binlog都能及时刷新到磁盘中,只要有了binlog,InnoDB就有办法做数据恢复,不至于导致主从复制的数据丢失。

    1. 在slave上修改配置
    master_info_repository = "TABLE"
    relay_log_info_repository = "TABLE"
    relay_log_recovery = 1
    

    上述前两个选项的作用是:确保在slave上和复制相关的元数据表也采用InnoDB引擎,受到InnoDB事务安全的保护,而后一个选项的作用是开启relay log自动修复机制,发生crash时,会自动判断哪些relay log需要重新从master上抓取回来再次应用,以此避免部分数据丢失的可能性。


    配置示例

    Master配置:

    开启远程连接
    使用命令行或者客户端工具进入 MySQL,执行命令:

    GRANT REPLICATION SLAVE ON *.* to 'root'@'192.168.0.108' identified by 'P@ssw0rd';
    FLUSH PRIVILEGES;
    

    上面语句执行完成后,在从服务器中使用客户端或者命令行测试是否生效。

    mysql -h 192.168.0.101 -uroot -p
    

    启用 bin-log,并设置 server-id
    需要在 MySQL 配置文件中修改,MySQL 配置文件默认位置在如下位置,从上下到下优先级降低:

    /etc/my.cnf
    /etc/mysql/my.cnf
    /usr/local/etc/my.cnf
    ~/.my.cnf
    

    配置内容如下:

    [mysqld]
    log-bin=mysql-bin
    server-id=101
    
    • 其他参数

    除了上面两个必要参数外,还有其他的几个参数。

    (1)binlog_format
    bin-log 日志的格式,支持下面三种,推荐使用 mixed 。

    statement:会将对数据库操作的sql语句写入到binlog中。
    row:会将每一条数据的变化写入到binlog中。
    mixed:statement 与 row 的混合。MySQL 决定什么时候写 statement 格式,什么时候写 row 格式。

    (2) binlog-do-db

    配置要同步的数据库,如果不配置默认为全部数据库。

    binlog-do-db=db1
    binlog-do-db=db2
    

    (3)binlog-ignore-db

    配置不需要同步的数据库。

    binlog-ignore-db=db3
    

    (4)expire-logs-days

    bin-log 日志保存天数,保存天数越久占用空间越大。

    然后重启 MySQL 服务

    mysql.server restart
    

    使用下面的命令可以查看配置是否生效:

    show variables like 'log_bin';
    show variables like 'server_id';
    

    使用下面的语句查看 master 状态。

    show master status;
    

    从服务器配置

    1、打开从服务器的配置文件,在其中加上如下配置:

    server-id=108
    

    2、重启 MySQL 服务。

    mysql.server restart
    

    3、配置主从同步

    change master to master_host='192.168.0.101',master_user='root',master_password='P@ssw0rd',master_log_file='mysql-bin.000001' ,master_log_pos=154;
    

    其中 master_host表示主服务器 IP,master_user和master_password分别是主服务器的用户名和密码,master_log_file和master_log_pos在主服务器中通过show master status语句可以查到。

    4、开启同步进程。

    start slave
    

    5、查看同步状态。

    show slave status;
    

    • Slave挂了怎么恢复同步?

    重启,只要同步服务再次启动,那就可以从上次同步的位置继续增量同步了。

    • 单Master挂了怎么办?

    如果马上启动那就是最好的解决办法。如果由于硬件或者比较棘手的问题导致没办法立即重启,那就要选一个从库升级为主库,选择的标准是数据最接近主库的,也就是最后一次同步时间最晚的。如果有可能(比如主服务只是数据库无法启动,但机器还在)还要到主服务上拉取最新的 bin-log 进行同步。最后进行一系列设置将选中的从库变更为主库配置。

    • 大致步骤:

    身份调换之前,主服务器会对表上锁,保证调换期间,不会写进新的数据。

    从服务器先停止从服务器IO线程,此期间,会应用完RelayLog中的所有信息,保证主、从数据完全一致。接下来,主、从服务器都会把自身的Binlog文件清除掉,建立起新的Binlog文件,再将之前两者的交互信息删干净,此时,可以重新建立主从连接了,从服务器俨然成为新一代主服务器,而原主服务器也解开之前的表锁,担起了从服务器的角色,事实证明,这是一次完美的试炼。

    相关文章

      网友评论

          本文标题:Mysql主从模式

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