• MYSQL高可用架构之MHA实战(真实可用)


    一:mysql主从复制原理

    1.1 用途和条件

    mysql主从复制用途

    • 实时灾备,用于故障切换
    • 读写分离,提供查询服务
    • 备份,避免影响业务

    主从部署必要条件:

    • 主库开启binlog日志(设置log-bin参数)
    • 主从server-id不同
    • 从库服务器能连通主库

    1.2 主从形式

    mysql主从复制 灵活

    • 一主一从
    • 主主复制
    • 一主多从---扩展系统读取的性能,因为读是在从库读取的;
    • 多主一从---5.7开始支持 联级复制---

    1.3 主从原理

    原理:

    (1)master服务器将数据的改变记录二进制binlog日志,当master上的数据发生改变时, 则将其改变写入binlog日志中;

    (2)slave服务器会在一定时间间隔内对master二进制日志进行探测其是否发生改变,如 果发生改变,则开始一个I/OThread请求master二进制事件

    (3)同时主节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至 从节点本地的中继日志中,从节点将启动SQL线程,从中继日志中读取二进制日志,在本 地重放,使得其数据和主节点的保持一致,最后I/OThread和SQLThread将进入睡眠状态, 等待下一次被唤醒。 主从复制配置的时候,从节点两个线程Slave_IO_Running 和Slave_SQL_Running状态必 须是Yes,就是上述两个线程

    也就是说:

    • 从库会生成两个线程,一个I/O线程,一个SQL线程;
    • I/O线程会去请求主库的binlog,并将得到的binlog写到本地的relay-log(中继日志)文件中;
    • 主库会生成一个log dump线程,用来给从库I/O线程传binlog;
    • SQL线程,会读取relay log文件中的日志,并解析成sql语句逐一执行;

    注意:

    1--master将操作语句记录到binlog日志中,然后授予slave远程连接的权限( master一定 要开启binlog二进制日志功能;通常为了数据安全考虑,slave也开启binlog功能 )。

    2--slave开启两个线程:IO线程和SQL线程。其中:IO线程负责读取master的binlog内容到 中继日志relay log里;SQL线程负责从relay log日志里读出binlog内容,并更新到slave的数 据库里,这样就能保证slave数据和master数据保持一致了。

    3--Mysql复制至少需要两个Mysql的服务,当然Mysql服务可以分布在不同的服务器上,也 可以在一台服务器上启动多个服务。

    4--Mysql复制最好确保master和slave服务器上的 Mysql版本相同 (如果不能满足版本一 致,那么要保证master主节点的版本低于slave从节点的版本)

    5--master和slave两节点间时间需同步

    二:MHA原理

    2.1 简介

    MHA(Master HA)是一款开源的 MySQL 的高可用程序,它为 MySQL主从复制架构提供了 automating master failover (自动化主故障转移)功能。MHA 在监控到 master 节点故障时,会 提升其中拥有最新数据的 slave 节点成为新的master 节点,在此期间,MHA 会通过于其它从节 点获取额外信息来避免一致性方面的问题。MHA 还提供了 master 节点的在线切换功能,即按需 切换 master/slave 节点。  

      MHA 是由日本人 yoshinorim(原就职于DeNA现就职于FaceBook)开发的比较成熟的 MySQL 高可用方案。MHA 能够在30秒内实现故障切换,并能在故障切换中,最大可能的保证数据一致 性。目前淘宝也正在开发相似产品 TMHA, 目前已支持一主一从。

    2.2 MHA 服务

      MHA 服务有两种角色, MHA Manager(管理节点)和 MHA Node(数据节点):

    MHA Manager: 通常单独部署在一台独立机器上管理多个 master/slave 集群(组),每个 master/slave 集群称作一个 application,用来管理统筹整个集群。

    MHA node: 运行在每台 MySQL 服务器上(master/slave/manager),它通过监控具备解析和清理

    logs 功能的脚本来加快故障转移: 主要是接收管理节点所发出指令的代理,代理需要运行在每一个 mysql 节点上。简单 讲 node 就是用来收集从节点服务器上所生成的 bin-log 。对比打算提升为新的主节点之上 的从节点的是否拥有并完成操作,如果没有发给新主节点在本地应用后提升为主节点。

    在MHA自动故障切换过程中,MHA试图从宕机的主服务器上保存二进制日志,最大程度的 保证数据的不丢失,但这并不总是可行的。例如,如果主服务器硬件故障或无法通过ssh访 问,MHA没法保存二进制日志,只进行故障转移而丢失了最新的数据。使用MySQL 5.5的 半同步复制,可以大大降低数据丢失的风险。MHA可以与半同步复制结合起来。如果只有 一个slave已经收到了最新的二进制日志,MHA可以将最新的二进制日志应用于其他所有的 slave服务器上,因此可以保证所有节点的数据一致性。

    由上图我们可以看出,每个复制组内部和 Manager 之间都需要ssh实现无密码互连,只有这样, 在 Master 出故障时, Manager 才能顺利的连接进去,实现主从切换功能。

    2.3 提供的工具

    MHA会提供诸多工具程序, 其常见的如下所示:

    Manager工具包主要包括以下几个工具:

    • masterha_check_ssh              检查MHA的SSH配置状况
    • masterha_check_repl             检查MySQL复制状况
    • masterha_manger                 启动MHA
    • masterha_check_status           检测当前MHA运行状态
    • masterha_master_monitor         检测master是否宕机
    • masterha_master_switch          控制故障转移(自动或者手动)
    • masterha_conf_host              添加或删除配置的server信息

    Node工具包(这些工具通常由MHA Manager的脚本触发,无需人为操作)主要包括以下几个工具:

    • save_binary_logs                保存和复制master的二进制日志
    • apply_diff_relay_logs           识别差异的中继日志事件并将其差异的事件应用于其他的slave
    • filter_mysqlbinlog              去除不必要的ROLLBACK事件(MHA已不再使用这个工具)
    • purge_relay_logs                清除中继日志(不会阻塞SQL线程)

    注意:

    为了尽可能的减少主库硬件损坏宕机造成的数据丢失,因此在配置MHA的同时建议配置成MySQL 5.5的半同步复制。关于半同步复制原理各位自己进行查阅。(不是必须)

    三: 安装和配置mysql主从复制架构

    3.1准备工作

    3.1.1 机器分配

    用四台服务器搭建MHA集群,各个服务器功能如下

    集群名称ip配置服务角色备注server-id
    managerM(如:192.168.0.1)Manager控制用于监控管理 -
    masterdb1(如:192.168.0.2)数据库主服务器

    开启 bin-log relay-log

    关闭 relay_log_purge

    1
    slave1db2(如:192.168.0.3)数据库从服务器1

    开启 bin-log relay-log

    关闭 relay_log_purge

    2
    slave2db3((如:192.168.0.4)数据库从服务器2

    开启 bin-log relay-log

    关闭 relay_log_purge

    3

    3.1.2 关闭防火墙

    所有节点进行初始化关闭防火墙

    1. systemctl status firewalld.service
    2. systemctl stop firewalld.service
    3. systemctl disable firewalld.service

    3.1.3 配置映射

    在各节点的/etc/hosts文件配置内容中添加如下内容:

    1. M(如:192.168.0.1) manager.zeromaster.com manager
    2. db1(如:192.168.0.2) master.zeromaster.com master
    3. db2(如:192.168.0.3) slave1.zeromaster.com slave1
    4. db3(如:192.168.0.4) slave2.zeromaster.com slave2

    这样的话,我们就可以通过 host 解析节点来打通私钥访问,会方便很多。

    3.2 安装mysql

    在centOS下安装Mysql数据库

    • 统一安装目录: /mha/mysql
    • 解压之后,的安装目录: /mha/mysql/install
    • 同一端口:3307
    • mysql安装包,mysql版本是5.7.23

    3.2.1 配置文件修改

    master 的配置文件 my.cnf,修改如下

    1. [client]
    2. port=3307
    3. socket=/mha/mysql/public/mysql/mysql.sock
    4. [mysql]
    5. character-set-server=utf8
    6. no-beep
    7. [mysqld]
    8. server-id=1
    9. log-bin=mysql-bin
    10. relay-log=mysql-relay-bin
    11. skip-name-resolve
    12. basedir=/mha/mysql/public/mysql
    13. datadir=/mha/mysql/public/mysql/data
    14. port=3307
    15. socket=/mha/mysql/public/mysql/mysql.sock
    16. log_error=/mha/mysql/public/mysql/error.log
    17. character-set-server=utf8
    18. sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    19. default-storage-engine=INNODB
    20. max_connections=1000
    21. lower_case_table_names=1
    22. skip-name-resolve
    23. init-connect='SET NAMES utf8mb4'
    24. character-set-server=utf8mb4
    25. wait_timeout=1800
    26. interactive_timeout=1800
    27. slow_query_log = ON
    28. slow_query_log_file = /mha/mysql/public/mysql/slow.log
    29. long_query_time = 1

    slave1从节点的配置文件my.cnf,修改如下

    1. [client]
    2. port=3307
    3. socket=/mha/mysql/install/public/mysql/mysql.sock
    4. [mysql]
    5. character-set-server=utf8
    6. no-beep
    7. [mysqld]
    8. server-id=2
    9. relay-log=relay-log
    10. log-bin=master-log
    11. read_only=ON
    12. relay_log_purge=0
    13. skip-name-resolve
    14. log_slave_updates=1
    15. basedir=/mha/mysql/install/public/mysql
    16. datadir=/mha/mysql/install/public/mysql/data
    17. port=3307
    18. socket=/mha/mysql/install/public/mysql/mysql.sock
    19. log_error=/mha/mysql/install/public/mysql/error.log
    20. character-set-server=utf8
    21. sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZE
    22. RO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    23. default-storage-engine=INNODB
    24. max_connections=1000
    25. lower_case_table_names=1

    slave2从节点的配置文件my.cnf,修改如下

    1. [client]
    2. port=3307
    3. socket=/mha/mysql/install/public/mysql/mysql.sock
    4. [mysql]
    5. character-set-server=utf8
    6. no-beep
    7. [mysqld]
    8. server-id=3
    9. relay-log=relay-log
    10. log-bin=master-log
    11. read_only=ON
    12. relay_log_purge=0
    13. skip-name-resolve
    14. log_slave_updates=1
    15. basedir=/mha/mysql/install/public/mysql
    16. datadir=/mha/mysql/install/public/mysql/data
    17. port=3307
    18. socket=/mha/mysql/install/public/mysql/mysql.sock
    19. log_error=/mha/mysql/install/public/mysql/error.log
    20. character-set-server=utf8
    21. sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZE
    22. RO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION
    23. default-storage-engine=INNODB
    24. max_connections=1000
    25. lower_case_table_names=1

    这里有几个需要注意的地方:

         MHA 对 MYSQL 复制环境有特殊要求,例如各节点都要开启二进制日志及中继日志,各从 节点必须显示启用其 read-only 属性,并关闭 relay_log_purge 功能等,从节点在 my.cnf配置文件中需要显示指定如下配置参数:

    1. relay-log = relay-log //开启中继日志
    2. read_only = ON //启用只读属性
    3. relay_log_purge = 0 //是否自动清空不再需要中继日志
    4. skip_name_resolve //关闭名称解析(非必须)
    5. log_slave_updates = 1 //使得更新的数据写进二进制日志中

    另外,根据后期踩坑: mysqlbinlog这个工具无法识别binlog中的配置中的defaultcharacter-set=utf8这个指令

    MySQL的配置/etc/my.cnf中将default-character-set=utf8 修改为 character-set-server = utf8

    1. #default-character-set=utf8
    2. character-set-server = utf8

    分别启动三个mysql服务

    3.2 权限配置

    3.2.1登录

    因为没有做软连接, 所以需要在/mha/mysql/install/public/mysql/bin 目录下登录mysql

    1. cd /mha/mysql/install/public/mysql/bin
    2. ./mysql -h 127.0.0.1 -P 3307 -u root -p\数据库密码

    此处使用的是 root@%账户,该账户需要授权,三个mysql集群都要操作。

    1. #给root@%用户 可以授权的权限
    2. select user,host,grant_priv from mysql.user;
    3. update mysql.user set Grant_priv = 'Y' where user = 'root';
    4. flush privileges;

    3.2.2:新建复制账户

    master新建复制账户

    master  节点,进入mysql,执行如下命令, 创建复制账号 slave,并授权,就是创建一个账户slave而不是root专门用来做复制之用。

    1. create user 'slave'@'%' identified by '123456';
    2. grant replication slave,replication client on *.* to 'slave'@'192.168.0.3'
    3. identified by '123456';
    4. grant replication slave,replication client on *.* to 'slave'@'192.168.0.4'
    5. identified by '123456';
    6. flush privileges;
    7. show master status;
    8. #获取到log_file 和 log_pos 的值

    slave1新建复制账户

    创建复制账户slave

    1. create user 'slave'@'%' identified by '123456';
    2. grant all privileges on *.* to 'slave'@'%' identified by '123456';
    3. flush privileges;

    slave2新建复制账户

    创建复制账户slave

    1. create user 'slave'@'%' identified by '123456';
    2. grant all privileges on *.* to 'slave'@'%' identified by '123456';
    3. flush privileges;

    3.2.3:主从复制配置

    master 获取状态

    1. #获取到log_file 和 log_pos 的值
    2. show master status;

    显示的是:

     得到 log_file: mysql-bin.000002 log_position: 1280

    slave1 指定master

    进入mysql,

    1. cd /mha/mysql/install/public/mysql/bin
    2. ./mysql -h 127.0.0.1 -P 3307 -u slave -p123456

    执行命令,指定master 。执行如下命令,指定master,这里指定的master用户,是 slave 也就是之前建立的专门复制的账户而不是root,当然也可以用 root。

    1. change master to master_host='db1(主192.168.0.2)',
    2. master_port=3308,master_user='slave',master_password='123456',master_log_file='mys
    3. ql-bin.000002',master_log_pos=1280;
    4. start slave;
    5. show slave status\G

    其中\G不能去掉哦。

    通过show slave status\G返回的信息是:

    1. *************************** 1. row ***************************
    2. Slave_IO_State: Waiting for master to send event
    3. Master_Host: db1(主192.168.0.2)
    4. Master_User: slave
    5. Master_Port: 3307
    6. Connect_Retry: 60
    7. Master_Log_File: mysql-bin.000002
    8. Read_Master_Log_Pos: 1280
    9. Relay_Log_File: relay-log.000002
    10. Relay_Log_Pos: 833
    11. Relay_Master_Log_File: mysql-bin.000002
    12. Slave_IO_Running: Yes
    13. Slave_SQL_Running: Yes
    14. Replicate_Do_DB:
    15. Replicate_Ignore_DB:
    16. Replicate_Do_Table:
    17. Replicate_Ignore_Table:
    18. Replicate_Wild_Do_Table:
    19. Replicate_Wild_Ignore_Table:
    20. Last_Errno: 0
    21. Last_Error:
    22. Skip_Counter: 0
    23. Exec_Master_Log_Pos: 1280
    24. Relay_Log_Space: 1034
    25. Until_Condition: None
    26. Until_Log_File:
    27. Until_Log_Pos: 0
    28. Master_SSL_Allowed: No
    29. Master_SSL_CA_File:
    30. Master_SSL_CA_Path:
    31. Master_SSL_Cert:
    32. Master_SSL_Cipher:
    33. Master_SSL_Key:
    34. Seconds_Behind_Master: 0
    35. Master_SSL_Verify_Server_Cert: No
    36. Last_IO_Errno: 0
    37. Last_IO_Error:
    38. Last_SQL_Errno: 0
    39. Last_SQL_Error:
    40. Replicate_Ignore_Server_Ids:
    41. Master_Server_Id: 1
    42. Master_UUID: 58ce17a5-2379-11ed-bce5-fa163e7cb7b7
    43. Master_Info_File: /mnt/mysql/public/mysql/data/master.info
    44. SQL_Delay: 0
    45. SQL_Remaining_Delay: NULL
    46. Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
    47. Master_Retry_Count: 86400
    48. Master_Bind:
    49. Last_IO_Error_Timestamp:
    50. Last_SQL_Error_Timestamp:
    51. Master_SSL_Crl:
    52. Master_SSL_Crlpath:
    53. Retrieved_Gtid_Set:
    54. Executed_Gtid_Set:
    55. Auto_Position: 0
    56. Replicate_Rewrite_DB:
    57. Channel_Name:
    58. Master_TLS_Version:

    Slave_IO_Running: Yes

    Slave_SQL_Running: Yes

    这两个进程显示都是YES,说明主从复制成功。 否则重新执行

    1. stop slave;
    2. change master to master_host='db1(主192.168.0.2)',
    3. master_port=3307,master_user='slave',master_password='123456',master_log_file='mys
    4. ql-bin.000002',master_log_pos=****;
    5. start slave;
    6. show slave status;

    直达成功。

    slave2 指定master

    参考slave1 指定master

    3.3 测试主从复制

    主库执行:create database bitch;

    查询从库是否创建bitch库。

    主从复制搭建成功!

  • 相关阅读:
    前端全局工具函数utils.js/正则(持续更新)
    网络安全—小白自学笔记
    自定义数据类型
    智能硬件开发怎么做?机智云全套自助式开发工具助力高效开发
    web前端(3)
    pyinstaller pyside6打包exe
    完美解决在Latex的表格里的单元格内的文本紧贴着上边框线条的问题
    Kafka生产调优实践。Kafka消息安全性、消息丢失、消息积压、保证消息顺序性
    没有gpedit.msc这个文件获取管理员权限
    大数据调优与传统数据调优之间有哪些异同点?
  • 原文地址:https://blog.csdn.net/wszhm123/article/details/126638300