MySQL - 读写分离

629 阅读6分钟

下面会向大家演示最常用的mysql主从配置方案,技术上没有太多复杂的地方,不过也可以满足大多数网站的性能对需求了

  • 知识点 (首先我们先了解一些必要的知识点, 这样大家可以之后的工作学习中可以从容的选择架构方案)

    ①:日志格式

        mysql提供了日志格式分别是 'Row' 'Statement' 'Mixed' 'GTID' , 下面我分别
        为大家介绍他们之间的区别
        
        'Row' 基于数据行的数据复制格式
            优点:
                -  使用随机函数和高精度时间函数可保证主从数据完全一致
                -  数据同步过程中从服务器产生的锁会比 'Statement' 格式更少
            缺点:
                -  主从复制时要求从服务器中的表结构必须完全一致(包括列顺序)   
        
        'Statement' 基于SQL语句的复制格式
            优点:
                - 产生的日志IO非常小, 通常是字节级别所以在传输时速度很快
                - 不强制要求主从数据库表完全相同
                - 相比于 'Row' 格式来说更加灵活
            缺点:
                - 调用随机函数时可能导致数据不一致
                '(比如UUID函数,时间函数等其他随机或精度函数)'
                
                - 相对于 'Row' 格式从服务器在操作会比前者产生出更多的行数
                '(也就是说在主服务器中锁了多少数据在从服务器还要在锁一次)'
        
        'Mixed' 混合复制格式(自动区分)
        
        'GTID'  (mysql5.6以上版本新增)
                - 与日志复制相比不会出现因为日志偏移量而产生的重复执行操作
        
    

    ②:主从复制原理

       '主库写入二进制日志->从服务器读取主库的二进制变更并写入relay_log->在从库重放relay_log中的日志'
    

    ③:主从复制方式

        '全同步复制 (Fully synchronous replication)'
         - 当主库执行完写入操作时将日志推送给所有从服务器,只有等所有从库都执行完成后才会将结果反馈给客户端
          (牺牲性能换取数据的一致性)
        
        '半同步复制 (Semisynchronous replication)'
         - 当主库执行完一次写入操作将日志推送给所有从服务器,只需等待一台服务器完成写入操作就会将结果反馈给客户端
          (介于全同步复制和异步复制之间的中间选择,适用于大多数应用场景)
        
        '异步复制 (Asynchronous replication)'
         - 如未进行配置时mysql默认采用异步复制,当产生新数据时主库会将binlog推送到从库,但是不保证一定能推送成功
          (简单来说就是,这事我已经告诉你了,你听没听到是你的事了!)
        
    
  • 准备工作

        ①   确认需要操作的服务器Mysql配置文件中都开启了 'log-bin=mysql-bin'
        ②   确认需要操作的服务器Mysql配置文件中 'server-id' 没有出现重复 
        ③   在从服务器Mysql配置文件中添加 'read_only' (选配项->只读模式, 如后续考虑配置MHA此项可不设置)
        ④   在从服务器Mysql配置文件中添加 'replicate-do-db' (选配项->从服务器指定库名)
        ⑤   停止业务运行等待配置完成后在开启服务以此保证数据的真实性(个人习惯)
        ⑥   选择适合自己项目的日志格式 '(如使用gtid复制则集群中所有服务器需开启如下参数,且gtid不支持mysql5.6以下版本)'
            gtid_mode = on
            enforce_gtid_consistency = on
            
    
  • 操作步骤

    ① 在主 (写) 服务器添加从 (读) 服务器用户

    
        # Mysql8以下添加用户
            mysql>   grant replication slave on 库名(*=全部).表名(*=全部) to '账号'@'服务器ip' identified by '连接密码';
        # Mysql8t添加用户
            mysql> create user '账号'@'服务器IP' identified by '密码';
            mysql> grant replication slave on 库名(*=全部).表名(*=全部) to '账号'@'服务器IP';
        # 刷新权限
        mysql>  flush privileges;
    

    ② 查询主服务器当前日志偏移量

        mysql>   show master status;
        # 如使用日志方式复制关注File及Position,如使用gtid复制关注Executed_Gtid_Set
    

    ③ 配置从 (读) 服务器

        # 基于日志点复制 (二选一)
        mysql>  change master to master_host='主服务器ip' (string),
            master_port=主服务器数据库端口 (int),
            master_user='从账号' (string),
            master_password='从密码' (string),
            master_log_file='主服务器当前的file值' (string),
            master_log_pos=主服务器当前的position (int);
        
        # 基于GTID复制 (二选一) 
        mysql> change master to master_host='主服务id' (string),
            master_port=主服务器数据库端口 (int),
            master_user='从账号' (string),
            master_password='从密码' (string),
            master_auto_position=日志点 (int)
        
        # 配的时候注意字段类型, 我第一次配的时候一直报错, 搞半天才发现是字段类型不对 
        mysql>   start slave     # 开始复制数据
        mysql>   show slave status\G     # 检查运行状态
        # Slave_IO_Running和Slave_SQL_Running都为Yse时表示连接成功
        # 也可以在主库上使用 show processlist 查看从库是否连接正常
    
  • 主从复制时可能产生的问题及解决方案分享

    ①  如何解决主从单点故障问题
        '单点故障在生产过程中无法避免,服务器重启,假死,断电,宕机都可能会造成单点
        故障, 解决方案可考虑使用双主多从架构,MMM架构,MHA架构, Mycat高可用配置'
        
    ②  如何解决主从复制时产生的单点数据延迟
        '使用主从复制时还会遇到这种情况,主服务器成功写入数据并将状态值反馈给客户端,
        此时客户端在读取刚才写入的数据时可能会出现找不到数据的情况(虽然说这种事情
        出现的概率很低),解决方案如下:'
        # 避免使用大事务,如在主库中一次性操作5万条以上的数据(如果真有需要可以拆开执行)
        # 开启多线程复制模式操作方法大家可以参考另外一篇分享
        # 如主从服务器都在同一个机房内则最好使用内网IP进行复制
        # 数据库服务器使用固态SSD硬盘以此提高读写效率
        # 主从服务器修改如下参数提高写入参数
            innodb_buffer_pool_size = 128M (值为当前服务器内存的80%) 
            innodb_log_file_size = 128M  (加到128M即可)
            innodb_log_buffer_size = 8M (加到64M即可)
            innodb_flush_log_at_trx_commit = 0
        # 如数据对一致性要求严苛建议采用全同步复制

至此,最简单的mysql主从复制就已经配置好了, 但是有一个问题,我是不是读操作要请求这台服务器,写操作要请求另外一台服务器呢? 就不能只请求一台服务器完成所有的操作吗?当然可以,篇幅有限,大家可以参考另外一篇博文

Mycat - 配置读写分离请求路由

Mysql - 多线程复制