当前位置:   article > 正文

Mysql orchestrator高可用

mysql orchestrator

一、什么是Orchestrator

Orchestrator是一款开源,对MySQL复制提供高可用、拓扑的可视化管理工具,采用go语言编写,它能够主动发现当前拓扑结构和主从复制状态,支持MySQL主从复制拓扑关系的调整、支持MySQL主库故障自动切换(failover)、手动主从切换(switchover)等功能。

Orchestrator后台依赖于MySQL或者SQLite存储元数据,能够提供Web界面展示MySQL集群的拓扑关系及实例状态,通过Web界面可更改MySQL实例的部分配置信息,同时也提供命令行和api接口,以便更加灵活的自动化运维管理。Orchestrator 对MySQL主库的故障切换分为自动切换和手动切换。手动切换又分为recover、force-master-failover、force-master-takeover以及graceful-master-takeover。

相比于MHA,Orchestrator更加偏重于复制拓扑关系的管理,能够实现MySQL任一复制拓扑关系的调整,并在此基础上,实现MySQL高可用。另外,Orchestrator自身也可以部署多个节点,通过raft分布式一致性协议,保证自身的高可用。

二、Orchestrator搭建

1、材料准备

主机hostname备注
192.168.88.129mysql_orch安装Orchestrator环境
192.168.88.130mysql00主库mysql8.0
192.168.88.131mysql01从库库mysql8.0
192.168.88.132mysql02从库库mysql8.0

a.修改hostname

vim /etc/sysconfig/network
hostname=mysql00

b.在每台机器上面配置

echo '192.168.88.129 mysql_orch' >> /etc/hosts
echo '192.168.88.130 mysql00' >> /etc/hosts
echo '192.168.88.131 mysql01' >> /etc/hosts
echo '192.168.88.132 mysql02' >> /etc/hosts

c.每台主机做免登录

ssh-keygen -t rsa ##enter键执行3次
ssh-copy-id -i ~/.ssh/id_rsa.pub mysql_orch
ssh-copy-id -i ~/.ssh/id_rsa.pub mysql00  ##含义是对192.168.88.130登录做免密
ssh-copy-id -i ~/.ssh/id_rsa.pub mysql01  ##含义是对192.168.88.131登录做免密
ssh-copy-id -i ~/.ssh/id_rsa.pub mysql02  ##含义是对192.168.88.132登录做免密

d.关闭每台电脑的防火墙

2、 搭建主从环境

主从环境就略过了,需要开启gtid,半同步增强复制。

在192.168.88.129的mysql上面创建Orchestrator账户,用于Orchestrator存储高可用架构的信息。还需要创建一个数据库

  1. CREATE DATABASE IF NOT EXISTS orchestrator;
  2. create user 'orchestrator'@'%' identified by '123456';
  3. GRANT ALL PRIVILEGES ON `orchestrator`.* TO 'orchestrator'@'%';

在192.168.88.130、192.168.88.131、192.168.88.132的mysql创建Orchestrator账户,用于Orchestrator,抓取各个mysql的信息,主从结构、切换mysql主从等。

  1. create user 'orchestrator'@'%' identified by '123456';
  2. GRANT SUPER, PROCESS, REPLICATION SLAVE, RELOAD ON *.* TO 'orchestrator'@'%';
  3. GRANT SELECT ON mysql.slave_master_info TO 'orchestrator'@'%';

这里需要在每台mysql中创建Orchestrator账户,

3、  安装Orchestrator

a. 下载Orchestrator 

GitHub - openark/orchestrator: MySQL replication topology management and HA

 orchestrator-3.2.6-1.x86_64.rpm

b. 安装orchestrator-3.2.6-1.x86_64.rpm

yum localinstall orchestrator-3.2.6-1.x86_64.rpm 即可,有需要的依赖包,安装即可。

c. orchestrator 配置文件配置

yum安装orchestrator后,安装路径在/usr/local/orchestrator目录

复制一份配置文件orchestrator.conf.json

 cp orchestrator-sample.conf.json orchestrator.conf.json

orchestrator.conf.json文件是一个json文件,主要配置以下参数

  1. {
  2. "Debug": true,
  3. "EnableSyslog": false,
  4. "ListenAddress": ":3000",
  5. "MySQLTopologyUser": "orchestrator",
  6. "MySQLTopologyPassword": "123456",
  7. "MySQLTopologyCredentialsConfigFile": "",
  8. "MySQLTopologySSLPrivateKeyFile": "",
  9. "MySQLTopologySSLCertFile": "",
  10. "MySQLTopologySSLCAFile": "",
  11. "MySQLTopologySSLSkipVerify": true,
  12. "MySQLTopologyUseMutualTLS": false,
  13. "MySQLOrchestratorHost": "192.168.88.129",
  14. "MySQLOrchestratorPort": 3306,
  15. "MySQLOrchestratorDatabase": "orchestrator",
  16. "MySQLOrchestratorUser": "orche",
  17. "MySQLOrchestratorPassword": "123456",
  18. "MySQLOrchestratorCredentialsConfigFile": "",
  19. "MySQLOrchestratorSSLPrivateKeyFile": "",
  20. "MySQLOrchestratorSSLCertFile": "",
  21. "MySQLOrchestratorSSLCAFile": "",
  22. "MySQLOrchestratorSSLSkipVerify": true,
  23. "MySQLOrchestratorUseMutualTLS": false,
  24. "MySQLConnectTimeoutSeconds": 1,
  25. "DefaultInstancePort": 3306,
  26. "DiscoverByShowSlaveHosts": true,
  27. "InstancePollSeconds": 5,
  28. "DiscoveryIgnoreReplicaHostnameFilters": [
  29. "a_host_i_want_to_ignore[.]example[.]com",
  30. ".*[.]ignore_all_hosts_from_this_domain[.]example[.]com",
  31. "a_host_with_extra_port_i_want_to_ignore[.]example[.]com:3307"
  32. ],
  33. "UnseenInstanceForgetHours": 240,
  34. "SnapshotTopologiesIntervalHours": 0,
  35. "InstanceBulkOperationsWaitTimeoutSeconds": 10,
  36. "HostnameResolveMethod": "default",
  37. "MySQLHostnameResolveMethod": "@@hostname",
  38. "SkipBinlogServerUnresolveCheck": true,
  39. "ExpiryHostnameResolvesMinutes": 60,
  40. "RejectHostnameResolvePattern": "",
  41. "ReasonableReplicationLagSeconds": 10,
  42. "ProblemIgnoreHostnameFilters": [],
  43. "VerifyReplicationFilters": false,
  44. "ReasonableMaintenanceReplicationLagSeconds": 20,
  45. "CandidateInstanceExpireMinutes": 60,
  46. "AuditLogFile": "",
  47. "AuditToSyslog": false,
  48. "RemoveTextFromHostnameDisplay": ".mydomain.com:3306",
  49. "ReadOnly": false,
  50. "AuthenticationMethod": "",
  51. "HTTPAuthUser": "",
  52. "HTTPAuthPassword": "",
  53. "AuthUserHeader": "",
  54. "PowerAuthUsers": [
  55. "*"
  56. ],
  57. "ClusterNameToAlias": {
  58. "127.0.0.1": "test suite"
  59. },
  60. "ReplicationLagQuery": "",
  61. "DetectClusterAliasQuery": "SELECT SUBSTRING_INDEX(@@hostname, '.', 1)",
  62. "DetectClusterDomainQuery": "",
  63. "DetectInstanceAliasQuery": "",
  64. "DetectPromotionRuleQuery": "",
  65. "DataCenterPattern": "[.]([^.]+)[.][^.]+[.]mydomain[.]com",
  66. "PhysicalEnvironmentPattern": "[.]([^.]+[.][^.]+)[.]mydomain[.]com",
  67. "PromotionIgnoreHostnameFilters": [],
  68. "DetectSemiSyncEnforcedQuery": "",
  69. "ServeAgentsHttp": false,
  70. "AgentsServerPort": ":3001",
  71. "AgentsUseSSL": false,
  72. "AgentsUseMutualTLS": false,
  73. "AgentSSLSkipVerify": false,
  74. "AgentSSLPrivateKeyFile": "",
  75. "AgentSSLCertFile": "",
  76. "AgentSSLCAFile": "",
  77. "AgentSSLValidOUs": [],
  78. "UseSSL": false,
  79. "UseMutualTLS": false,
  80. "SSLSkipVerify": false,
  81. "SSLPrivateKeyFile": "",
  82. "SSLCertFile": "",
  83. "SSLCAFile": "",
  84. "SSLValidOUs": [],
  85. "URLPrefix": "",
  86. "StatusEndpoint": "/api/status",
  87. "StatusSimpleHealth": true,
  88. "StatusOUVerify": false,
  89. "AgentPollMinutes": 60,
  90. "UnseenAgentForgetHours": 6,
  91. "StaleSeedFailMinutes": 60,
  92. "SeedAcceptableBytesDiff": 8192,
  93. "PseudoGTIDPattern": "",
  94. "PseudoGTIDPatternIsFixedSubstring": false,
  95. "PseudoGTIDMonotonicHint": "asc:",
  96. "DetectPseudoGTIDQuery": "",
  97. "BinlogEventsChunkSize": 10000,
  98. "SkipBinlogEventsContaining": [],
  99. "ReduceReplicationAnalysisCount": true,
  100. "FailureDetectionPeriodBlockMinutes": 1,
  101. "FailMasterPromotionOnLagMinutes": 0,
  102. "RecoveryPeriodBlockSeconds": 30,
  103. "RecoveryIgnoreHostnameFilters": [],
  104. "RecoverMasterClusterFilters": [
  105. "*"
  106. ],
  107. "RecoverIntermediateMasterClusterFilters": [
  108. "*"
  109. ],
  110. "OnFailureDetectionProcesses": [
  111. "echo 'Detected {failureType} on {failureCluster}. Affected replicas: {countSlaves}' >> /tmp/recovery.log"
  112. ],
  113. "PreGracefulTakeoverProcesses": [
  114. "echo 'Planned takeover about to take place on {failureCluster}. Master will switch to read_only' >> /tmp/recovery.log"
  115. ],
  116. "PreFailoverProcesses": [
  117. "echo 'Will recover from {failureType} on {failureCluster}' >> /tmp/recovery.log"
  118. ],
  119. "PostFailoverProcesses": [
  120. "echo '(for all types) Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Successor: {successorHost}:{successorPort}{failureClusterAlias}' >> /tmp/recovery.log", "/home/orch/orch_hook.sh {failureType} {failureClusterAlias} {failedHost} {successorHost} >> /tmp/orch.log"
  121. ],
  122. "PostUnsuccessfulFailoverProcesses": [],
  123. "PostMasterFailoverProcesses": [
  124. "echo 'Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Promoted: {successorHost}:{successorPort}' >> /tmp/recovery.log"
  125. ],
  126. "PostIntermediateMasterFailoverProcesses": [
  127. "echo 'Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Successor: {successorHost}:{successorPort}' >> /tmp/recovery.log"
  128. ],
  129. "PostGracefulTakeoverProcesses": [
  130. "echo 'Planned takeover complete' >> /tmp/recovery.log"
  131. ],
  132. "CoMasterRecoveryMustPromoteOtherCoMaster": true,
  133. "DetachLostSlavesAfterMasterFailover": true,
  134. "ApplyMySQLPromotionAfterMasterFailover": true,
  135. "PreventCrossDataCenterMasterFailover": false,
  136. "PreventCrossRegionMasterFailover": false,
  137. "MasterFailoverDetachReplicaMasterHost": false,
  138. "MasterFailoverLostInstancesDowntimeMinutes": 0,
  139. "PostponeReplicaRecoveryOnLagMinutes": 0,
  140. "OSCIgnoreHostnameFilters": [],
  141. "GraphiteAddr": "",
  142. "GraphitePath": "",
  143. "GraphiteConvertHostnameDotsToUnderscores": true,
  144. "ConsulAddress": "",
  145. "ConsulAclToken": "",
  146. "ConsulKVStoreProvider": "consul"
  147. }

配置修改:

MySQLTopologyUser 和 MySQLTopologyPassword

表示的是192.168.88.130、192.168.88.131、192.168.88.132上面的mysql账户

"MySQLOrchestratorHost": "192.168.88.129",
"MySQLOrchestratorPort": 3306,
"MySQLOrchestratorDatabase": "orchestrator",
"MySQLOrchestratorUser": "orche",
"MySQLOrchestratorPassword": "123456",

上面的参数对应的是192.168.88.129对应的存储Orchestrator信息的数据库,这里一定要理解清楚,很容易搞混淆。

RecoverMasterClusterFilters
RecoverIntermediateMasterClusterFilters

两个参数建议都配置 * ,不然后面多次切换主从的时候,第二次不会成功

RecoveryPeriodBlockSeconds 3600 ##已经出故障后切换 3600s 后才能切换下一次
FailureDetectionPeriodBlockMinutes 1 在该时间内再次出现故障,不会被多次发现

如果在测试的环境把这两个值调小一点,不然多次切换主从会有问题

d. 启动orchestrator

在/usr/local/orchestrator 目录下执行

nohup ./orchestrator --debug http > orc.log 2>&1 &

f. 进入orchestrator web页面

http://192.168.88.129:3000/

 可以在discover中添加我们的mysql主从集群,在hostname中输入主库192.168.88.130,点击submit按钮即可,

如果能连接上就有下面的拓扑结构图

三、其他相关问题

1. 测试自动切换主从

可以把192.168.88.130的mysql关闭后,刷新Orchestrator就可以看到,Orchestrator会自动选主。

2.  orchestrator 是怎么检测主库挂掉的

a.orch会先检测主库,如果联系不上主库
b.判断能连接上的所有从库是否能联系上主库,如果a和b都不行,则判断主库已经挂掉了

orch检测主库宕机依赖从库的IO线程(本身连不上主库后,还会通过从库再去检测主库是否异常),所以默认change搭建的主从感知主库宕机的等待时间过长,需要需要稍微改下

change master to master_host='192.168.163.131',master_port=3307,master_user='rep',master_password='rep',master_auto_position=1,MASTER_HEARTBEAT_PERIOD=2,MASTER_CONNECT_RETRY=1, MASTER_RETRY_COUNT=86400;

set global slave_net_timeout=8;##判断slave是否与主机断掉了,超时时间

slave_net_timeout 表示slave在slave_net_timeout时间之内没有收到master的任何数据(包括binlog,heartbeat),slave认为连接断开,需要重连。默认值60s。


MASTER_HEARTBEAT_PERIOD 表示心跳的周期。当MASTER_HEARTBEAT_PERIOD时间之内,master没有binlog event发送给slave的时候,就会发送心跳数据给slave

MASTER_CONNECT_RETRY
slave_net_timeout超时后,立刻重连,后续重连的时间间隔由 CHANGE MASTER TO 命令的MASTER_CONNECT_RETRY 参数指定。默认值60s。

MASTER_RETRY_COUNT 限制重连次数

3. orchestrator 是如何选主的

 考虑从库执行的位置点、数据中心、版本的兼容、binlog格式、是否满足相应的参数、promotion_rule规则的判定等等,来寻找一个符合设定条件的候选节点并尝试提升其为新的主库,从而完成自动故障恢复
默认会选Executed_Gtid_Set最大的,数据最全的

4.  是否会有丢失数据的风险

有一些原因确实有丢失数据,造成主从不一致,因为orch不会主动的去补数据。所以一定要使用gtid和半同步增加复制。

5. 从库升级主库后,old主库怎么处理

检查old主库和new主库的数据有没有不同,然后change master to执行就好了

change master to master_host='192.168.88.130', master_port=3306, master_user='repl', master_password='123456', master_auto_position=1, MASTER_HEARTBEAT_PERIOD=2,MASTER_CONNECT_RETRY=1, MASTER_RETRY_COUNT=86400;

6. vip怎么漂移

Orchestrator中配置钩子,在orchestrator.conf.json配置文件中,添加

 逻辑就是:在PostFailoverProcesses配置中添加一个shell脚本,orchestrator主从切换成功以后就会执行这个脚本。上面也可以配置不同的钩子,在orchestrator不同状态下执行对于的脚本。这里只讲vip相关的。

"/home/orch/orch_hook.sh {failureType} {failureClusterAlias} {failedHost} {successorHost} >> /tmp/orch.log"

有问题可以看上面的配置文件,里面直接复制

a、所以我们的shell脚本就在 /home/orch/orch_hook.sh 中

  1. #!/bin/bash
  2. isitdead=$1
  3. cluster=$2
  4. oldmaster=$3
  5. newmaster=$4
  6. mysqluser="orchestrator"
  7. export MYSQL_PWD="123456"
  8. logfile="/var/log/orch_hook.log"
  9. # list of clusternames
  10. #clusternames=(rep blea lajos)
  11. # clustername=( interface IP user Inter_IP)
  12. #rep=( ens32 "192.168.56.121" root "192.168.56.125")
  13. if [[ $isitdead == "DeadMaster" ]]; then
  14. array=( ens33 "192.168.88.200" root "192.168.88.129")
  15. interface=${array[0]}
  16. IP=${array[1]}
  17. user=${array[2]}
  18. if [ ! -z ${IP} ] ; then
  19. echo $(date)
  20. echo "Revocering from: $isitdead"
  21. echo "New master is: $newmaster"
  22. echo "/usr/local/orchestrator/orch_vip.sh -d 1 -n $newmaster -i ${interface} -I ${IP} -u ${user} -o $oldmaster" | tee $logfile
  23. /usr/local/orchestrator/orch_vip.sh -d 1 -n $newmaster -i ${interface} -I ${IP} -u ${user} -o $oldmaster
  24. #mysql -h$newmaster -u$mysqluser < /usr/local/bin/orch_event.sql
  25. else
  26. echo "Cluster does not exist!" | tee $logfile
  27. fi
  28. elif [[ $isitdead == "DeadIntermediateMasterWithSingleSlaveFailingToConnect" ]]; then
  29. array=( ens33 "192.168.88.200" root "192.168.88.129")
  30. interface=${array[0]}
  31. IP=${array[1]}
  32. user=${array[2]}
  33. slavehost=`echo $5 | cut -d":" -f1`
  34. echo $(date)
  35. echo "Revocering from: $isitdead"
  36. echo "New intermediate master is: $slavehost"
  37. echo "/usr/local/orchestrator/orch_vip.sh -d 1 -n $slavehost -i ${interface} -I ${IP} -u ${user} -o $oldmaster" | tee $logfile
  38. /usr/local/orchestrator/orch_vip.sh -d 1 -n $slavehost -i ${interface} -I ${IP} -u ${user} -o $oldmaster
  39. elif [[ $isitdead == "DeadIntermediateMaster" ]]; then
  40. array=( ens33 "192.168.88.200" root "192.168.88.129")
  41. interface=${array[0]}
  42. IP=${array[3]}
  43. user=${array[2]}
  44. slavehost=`echo $5 | sed -E "s/:[0-9]+//g" | sed -E "s/,/ /g"`
  45. showslave=`mysql -h$newmaster -u$mysqluser -sN -e "SHOW SLAVE HOSTS;" | awk '{print $2}'`
  46. newintermediatemaster=`echo $slavehost $showslave | tr ' ' '\n' | sort | uniq -d`
  47. echo $(date)
  48. echo "Revocering from: $isitdead"
  49. echo "New intermediate master is: $newintermediatemaster"
  50. echo "/usr/local/orchestrator/orch_vip.sh -d 1 -n $newintermediatemaster -i ${interface} -I ${IP} -u ${user} -o $oldmaster" | tee $logfile
  51. /usr/local/orchestrator/orch_vip.sh -d 1 -n $newintermediatemaster -i ${interface} -I ${IP} -u ${user} -o $oldmaster
  52. fi

上面的脚本需要修改的地方 array=( ens33 "192.168.88.200" root "192.168.88.129")

ens33表示网卡,填自己的电脑上面的

192.168.88.200 表示vip地址

192.168.88.129 表示orchestrator安装的ip

root 表示免登录的linux账户

b、/usr/local/orchestrator/orch_vip.sh 漂移脚本

  1. #!/bin/bash
  2. isitdead=$1
  3. cluster=$2
  4. oldmaster=$3
  5. newmaster=$4
  6. mysqluser="orchestrator"
  7. export MYSQL_PWD="123456"
  8. logfile="/var/log/orch_hook.log"
  9. # list of clusternames
  10. #clusternames=(rep blea lajos)
  11. # clustername=( interface IP user Inter_IP)
  12. #rep=( ens32 "192.168.56.121" root "192.168.56.125")
  13. if [[ $isitdead == "DeadMaster" ]]; then
  14. array=( ens33 "192.168.88.200" root "192.168.88.129")
  15. interface=${array[0]}
  16. IP=${array[1]}
  17. user=${array[2]}
  18. if [ ! -z ${IP} ] ; then
  19. echo $(date)
  20. echo "Revocering from: $isitdead"
  21. echo "New master is: $newmaster"
  22. echo "/usr/local/orchestrator/orch_vip.sh -d 1 -n $newmaster -i ${interface} -I ${IP} -u ${user} -o $oldmaster" | tee $logfile
  23. /usr/local/orchestrator/orch_vip.sh -d 1 -n $newmaster -i ${interface} -I ${IP} -u ${user} -o $oldmaster
  24. #mysql -h$newmaster -u$mysqluser < /usr/local/bin/orch_event.sql
  25. else
  26. echo "Cluster does not exist!" | tee $logfile
  27. fi
  28. elif [[ $isitdead == "DeadIntermediateMasterWithSingleSlaveFailingToConnect" ]]; then
  29. array=( ens33 "192.168.88.200" root "192.168.88.129")
  30. interface=${array[0]}
  31. IP=${array[1]}
  32. user=${array[2]}
  33. slavehost=`echo $5 | cut -d":" -f1`
  34. echo $(date)
  35. echo "Revocering from: $isitdead"
  36. echo "New intermediate master is: $slavehost"
  37. echo "/usr/local/orchestrator/orch_vip.sh -d 1 -n $slavehost -i ${interface} -I ${IP} -u ${user} -o $oldmaster" | tee $logfile
  38. /usr/local/orchestrator/orch_vip.sh -d 1 -n $slavehost -i ${interface} -I ${IP} -u ${user} -o $oldmaster
  39. elif [[ $isitdead == "DeadIntermediateMaster" ]]; then
  40. array=( ens33 "192.168.88.200" root "192.168.88.129")
  41. interface=${array[0]}
  42. IP=${array[3]}
  43. user=${array[2]}
  44. slavehost=`echo $5 | sed -E "s/:[0-9]+//g" | sed -E "s/,/ /g"`
  45. showslave=`mysql -h$newmaster -u$mysqluser -sN -e "SHOW SLAVE HOSTS;" | awk '{print $2}'`
  46. newintermediatemaster=`echo $slavehost $showslave | tr ' ' '\n' | sort | uniq -d`
  47. echo $(date)
  48. echo "Revocering from: $isitdead"
  49. echo "New intermediate master is: $newintermediatemaster"
  50. echo "/usr/local/orchestrator/orch_vip.sh -d 1 -n $newintermediatemaster -i ${interface} -I ${IP} -u ${user} -o $oldmaster" | tee $logfile
  51. /usr/local/orchestrator/orch_vip.sh -d 1 -n $newintermediatemaster -i ${interface} -I ${IP} -u ${user} -o $oldmaster
  52. fi
  53. [root@localhost orchestrator]# cat /usr/local/orchestrator/orch_vip.sh
  54. #!/bin/bash
  55. emailaddress="email@example.com"
  56. sendmail=0
  57. function usage {
  58. cat << EOF
  59. usage: $0 [-h] [-d master is dead] [-o old master ] [-s ssh options] [-n new master] [-i interface] [-I] [-u SSH user]
  60. OPTIONS:
  61. -h Show this message
  62. -o string Old master hostname or IP address
  63. -d int If master is dead should be 1 otherweise it is 0
  64. -s string SSH options
  65. -n string New master hostname or IP address
  66. -i string Interface exmple eth0:1
  67. -I string Virtual IP
  68. -u string SSH user
  69. EOF
  70. }
  71. while getopts ho:d:s:n:i:I:u: flag; do
  72. case $flag in
  73. o)
  74. orig_master="$OPTARG";
  75. ;;
  76. d)
  77. isitdead="${OPTARG}";
  78. ;;
  79. s)
  80. ssh_options="${OPTARG}";
  81. ;;
  82. n)
  83. new_master="$OPTARG";
  84. ;;
  85. i)
  86. interface="$OPTARG";
  87. ;;
  88. I)
  89. vip="$OPTARG";
  90. ;;
  91. u)
  92. ssh_user="$OPTARG";
  93. ;;
  94. h)
  95. usage;
  96. exit 0;
  97. ;;
  98. *)
  99. usage;
  100. exit 1;
  101. ;;
  102. esac
  103. done
  104. if [ $OPTIND -eq 1 ]; then
  105. echo "No options were passed";
  106. usage;
  107. fi
  108. shift $(( OPTIND - 1 ));
  109. # discover commands from our path
  110. ssh=$(which ssh)
  111. arping=$(which arping)
  112. ip2util=$(which ip)
  113. # command for adding our vip
  114. cmd_vip_add="sudo -n $ip2util address add ${vip} dev ${interface}"
  115. # command for deleting our vip
  116. cmd_vip_del="sudo -n $ip2util address del ${vip}/32 dev ${interface}"
  117. # command for discovering if our vip is enabled
  118. cmd_vip_chk="sudo -n $ip2util address show dev ${interface} to ${vip%/*}/32"
  119. # command for sending gratuitous arp to announce ip move
  120. cmd_arp_fix="sudo -n $arping -c 1 -I ${interface} ${vip%/*} "
  121. # command for sending gratuitous arp to announce ip move on current server
  122. cmd_local_arp_fix="sudo -n $arping -c 1 -I ${interface} ${vip%/*} "
  123. vip_stop() {
  124. rc=0
  125. # ensure the vip is removed
  126. $ssh ${ssh_options} -tt ${ssh_user}@${orig_master} \
  127. "[ -n \"\$(${cmd_vip_chk})\" ] && ${cmd_vip_del} && sudo ${ip2util} route flush cache || [ -z \"\$(${cmd_vip_chk})\" ]"
  128. rc=$?
  129. return $rc
  130. }
  131. vip_start() {
  132. rc=0
  133. # ensure the vip is added
  134. # this command should exit with failure if we are unable to add the vip
  135. # if the vip already exists always exit 0 (whether or not we added it)
  136. $ssh ${ssh_options} -tt ${ssh_user}@${new_master} \
  137. "[ -z \"\$(${cmd_vip_chk})\" ] && ${cmd_vip_add} && ${cmd_arp_fix} || [ -n \"\$(${cmd_vip_chk})\" ]"
  138. rc=$?
  139. $cmd_local_arp_fix
  140. return $rc
  141. }
  142. vip_status() {
  143. $arping -c 1 -I ${interface} ${vip%/*}
  144. if ping -c 1 -W 1 "$vip"; then
  145. return 0
  146. else
  147. return 1
  148. fi
  149. }
  150. if [[ $isitdead == 0 ]]; then
  151. echo "Online failover"
  152. if vip_stop; then
  153. if vip_start; then
  154. echo "$vip is moved to $new_master."
  155. if [ $sendmail -eq 1 ]; then mail -s "$vip is moved to $new_master." "$emailaddress" < /dev/null &> /dev/null ; fi
  156. else
  157. echo "Can't add $vip on $new_master!"
  158. if [ $sendmail -eq 1 ]; then mail -s "Can't add $vip on $new_master!" "$emailaddress" < /dev/null &> /dev/null ; fi
  159. exit 1
  160. fi
  161. else
  162. echo $rc
  163. echo "Can't remove the $vip from orig_master!"
  164. if [ $sendmail -eq 1 ]; then mail -s "Can't remove the $vip from orig_master!" "$emailaddress" < /dev/null &> /dev/null ; fi
  165. exit 1
  166. fi
  167. elif [[ $isitdead == 1 ]]; then
  168. echo "Master is dead, failover"
  169. # make sure the vip is not available
  170. if vip_status; then
  171. if vip_stop; then
  172. if [ $sendmail -eq 1 ]; then mail -s "$vip is removed from orig_master." "$emailaddress" < /dev/null &> /dev/null ; fi
  173. else
  174. if [ $sendmail -eq 1 ]; then mail -s "Couldn't remove $vip from orig_master." "$emailaddress" < /dev/null &> /dev/null ; fi
  175. exit 1
  176. fi
  177. fi
  178. if vip_start; then
  179. echo "$vip is moved to $new_master."
  180. if [ $sendmail -eq 1 ]; then mail -s "$vip is moved to $new_master." "$emailaddress" < /dev/null &> /dev/null ; fi
  181. else
  182. echo "Can't add $vip on $new_master!"
  183. if [ $sendmail -eq 1 ]; then mail -s "Can't add $vip on $new_master!" "$emailaddress" < /dev/null &> /dev/null ; fi
  184. exit 1
  185. fi
  186. else
  187. echo "Wrong argument, the master is dead or live?"
  188. fi

上面两个文件记得权限和可执行的问题。

c.测试漂移

在主库添加vip
ip addr add 192.168.88.200 dev ens33

然后关闭主库的mysql,看看主从切换后,vip地址是否也切换

上面如果有问题的日志可以看

/var/log/orch_hook.log

/tmp/recovery.log

细节:一定要配置免登录,否则不可能成功,orch_vip.sh这个脚本需要到新的主库linux上面去绑定vip的

四、参考博文

感谢下面的大佬的资料,感谢感谢!

##这个文章是真的不错
https://www.cnblogs.com/chasetimeyang/p/15063858.html
https://www.cnblogs.com/dh17/articles/14790321.html

##这个问题很不错啊
https://blog.csdn.net/baijiu1/article/details/89395654

https://blog.csdn.net/du18020126395/article/details/115289099
https://www.cnblogs.com/zhoujinyi/p/10394389.html

##写的不错
https://www.cnblogs.com/chasetimeyang/p/15063858.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/889952
推荐阅读
相关标签
  

闽ICP备14008679号