歡迎光臨
每天分享高質量文章

MySQL如何實現高可用?

Orchestrator功能強大,能適應多種恢復場景,通過呼叫WEB接口和命令orchestrator-client能完成非常多的功能。 

 

本文介紹了Orchestrator的幾種應用場景,以及雲和恩墨自主研發的MySQL整體解決方案MyData是如何基於Orchestrator進行優化,實現資料庫高可用的。

Orchestrator簡介

Orchestrator是近年出現的基於GO語言編寫的MySQL HA開源管理工具,相較與傳統的HA(MHA、MMM等)管理工具,Orchestrator提供了展示MySQL複製拓撲關係及狀態的Web界面,支持在Web界面管理/變更資料庫複製管理,同時Orchestrator提供了豐富的命令列指令和WEB接口,並支持多節點集群方式部署。

MyData使用Orchestrator實現資料庫高可用

Orchestrator的特點

  • 支持自動發現MySQL的複製拓撲圖

  • 支持通過圖形界面操作或呼叫接口變更複製關係

  • 支持自動檢測主庫異常:主庫故障檢測,Orchestrator會同時連接主庫和從庫,當管理節點檢測到主庫異常時,會通過從庫再次確認主庫是否異常,這樣規避了一些對主庫故障錯誤判斷的場景

  • 支持多種型別恢復:自動恢復、優雅的恢復、手動恢復、手動強制恢復

  • 支持中繼主庫(DeadIntermediateMaster)和主庫恢復

  • 提供多個Hooks接口優化恢復流程

  • 本身支持多節點,通過raft協議保證集群高可用

Orchestrator的安裝配置

1. 配置yum源

curl -s https://packagecloud.io/install/repositories/github/orchestrator/script.rpm.sh|bashyum install -y epel-release

2. 安裝orchestrator(3.0.14)

yum install -y orchestrator

3. 環境配置

MySQL(版本5.7.24),共三個節點主節點,192.168.11.175:22222從節點,192.168.11.176:22222從節點,192.168.11.177:22222orchestrator管理節點:192.168.11.179:3000

4. 安裝配置orchestrator 使用的MySQL資料庫

CREATE DATABASE IF NOT EXISTS orchestrator;CREATE USER 'orchestrator'@'%' IDENTIFIED BY 'orch_backend_password';GRANT ALL PRIVILEGES ON 'orchestrator'.* TO 'orchestrator'@'%';

5. 被管理資料庫配置要求(MySQL5.7+)

gtid-mode = ONenforce_gtid_consistency = 1binlog_format = ROWlog-bin =/data/mysql/data/mysql-binslave_preserve_commit_order=1report_host = 192.168.11.175master-info-repository = TABLElog_slave_updates = 1

6. MyDATA優化

對於資料庫集群需要一些特定的配置,否則orchestrator不能發現集群或者對管理的集群不能正常完成故障切換(例如未配置log_slave_updates = 1或者多執行緒未配置slave_preserve_commit_order=1等),MyData在這裡做了一些優化,根據orchestrator的配置檢查資料庫集群的配置,對於預期不能正常切換的資料庫集群打印出告警信息,用戶可以根據告警信息修改資料庫集群配置

7. 配置orchestrator監控和切換用戶:

CREATE USER 'orchestrator'@'%' IDENTIFIED BY 'orch_topology_password';GRANT SUPER, PROCESS, REPLICATION SLAVE, RELOAD ON *.* TO 'orchestrator'@'%';GRANT SELECT ON mysql.slave_master_info TO 'orchestrator'@'%';GRANT SELECT ON mysql.mydata_cluster TO 'orchestrator'@'%';

8. 配置集群別名

use mysql;CREATE TABLE `mydata_cluster` (  `anchor` tinyint(4NOT NULL,  `cluster_name` varchar(128NOT NULL DEFAULT '',  `cluster_domain` varchar(128NOT NULL DEFAULT '',  PRIMARY KEY (`anchor`));replace into mydata_cluster values (1,'cluster01','test');

9. 修改orchestrator配置(/usr/local/orchestrator/orchestrator.conf.json)

{  "Debug"true,     "EnableSyslog"false,    "ListenAddress"":3000",    "MySQLTopologyUser""orchestrator",    "MySQLTopologyPassword": "orch_topology_password",
  "MySQLTopologyCredentialsConfigFile": "",
  "MySQLTopologySSLPrivateKeyFile": "",
  "MySQLTopologySSLCertFile": "",
  "MySQLTopologySSLCAFile": "",
  "MySQLTopologySSLSkipVerify": true,
  "MySQLTopologyUseMutualTLS": false,
  "MySQLOrchestratorHost": "192.168.11.179",
  "MySQLOrchestratorPort": 3306,
  "MySQLOrchestratorDatabase": "orchestrator",
  "MySQLOrchestratorUser": "orchestrator",
  "MySQLOrchestratorPassword": "orch_backend_password",
  "MySQLConnectionLifetimeSeconds": 10,
  "MySQLOrchestratorCredentialsConfigFile": "",
  "MySQLOrchestratorSSLPrivateKeyFile": "",
  "MySQLOrchestratorSSLCertFile": "",
  "MySQLOrchestratorSSLCAFile": "",
  "MySQLOrchestratorSSLSkipVerify": true,
  "MySQLOrchestratorUseMutualTLS": false,
  "MySQLConnectTimeoutSeconds": 1,
  "DefaultInstancePort": 3306,
  "DiscoverByShowSlaveHosts": true,
  "InstancePollSeconds": 5,
  "UnseenInstanceForgetHours": 240,
  "SnapshotTopologiesIntervalHours": 0,
  "InstanceBulkOperationsWaitTimeoutSeconds": 10,
  "HostnameResolveMethod": "default",
  "MySQLHostnameResolveMethod": "@@report_host",
  "SkipBinlogServerUnresolveCheck": true,
  "ExpiryHostnameResolvesMinutes": 60,
  "RejectHostnameResolvePattern": "",
  "ReasonableReplicationLagSeconds": 10,
  "ProblemIgnoreHostnameFilters": [],
  "VerifyReplicationFilters": false,
  "ReasonableMaintenanceReplicationLagSeconds": 20,
  "CandidateInstanceExpireMinutes": 60,
  "AuditLogFile": "",
  "AuditToSyslog": false,
  "RemoveTextFromHostnameDisplay": ".mydomain.com:3306",
  "ReadOnly": false,
  "AuthenticationMethod": "",
  "HTTPAuthUser": "",
  "HTTPAuthPassword": "",
  "AuthUserHeader": "",
  "UseSuperReadOnly": true,
  "FailMasterPromotionIfSQLThreadNotUpToDate": false,
  "PowerAuthUsers": [
    "*"
  ],
  "ClusterNameToAlias": {
    "192.168.11.179": "test suite"
  },
  "SlaveLagQuery": "",
  "DetectClusterAliasQuery": "select ifnull(max(cluster_name),concat(ifnull(@@report_host,@@hostname),':',@@report_port)) from mysql.mydata_cluster where anchor=1",
  "DetectClusterDomainQuery": "",
  "DetectInstanceAliasQuery": "",
  "DetectPromotionRuleQuery": "",
  "DataCenterPattern": "[.]([^.]+)[.][^.]+[.]mydomain[.]com",
  "PhysicalEnvironmentPattern": "[.]([^.]+[.][^.]+)[.]mydomain[.]com",
  "PromotionIgnoreHostnameFilters": [],
  "DetectSemiSyncEnforcedQuery": "",
  "ServeAgentsHttp": false,
  "AgentsServerPort": ":3001",
  "AgentsUseSSL": false,
  "AgentsUseMutualTLS": false,
  "AgentSSLSkipVerify": false,
  "AgentSSLPrivateKeyFile": "",
  "AgentSSLCertFile": "",
  "AgentSSLCAFile": "",
  "AgentSSLValidOUs": [],
  "UseSSL": false,
  "UseMutualTLS": false,
  "SSLSkipVerify": false,
  "SSLPrivateKeyFile": "",
  "SSLCertFile": "",
  "SSLCAFile": "",
  "SSLValidOUs": [],
  "URLPrefix": "",
  "StatusEndpoint": "/api/status",
  "StatusSimpleHealth": true,
  "StatusOUVerify": false,
  "AgentPollMinutes": 60,
  "UnseenAgentForgetHours": 6,
  "StaleSeedFailMinutes": 60,
  "SeedAcceptableBytesDiff": 8192,
  "PseudoGTIDPattern": "",
  "PseudoGTIDPatternIsFixedSubstring": false,
  "PseudoGTIDMonotonicHint": "asc:",
  "DetectPseudoGTIDQuery": "",
  "BinlogEventsChunkSize": 10000,
  "SkipBinlogEventsContaining": [],
  "ReduceReplicationAnalysisCount": true,
  "FailureDetectionPeriodBlockMinutes": 60,
  "RecoveryPeriodBlockSeconds": 3600,
  "RecoveryIgnoreHostnameFilters": [],
  "RecoverMasterClusterFilters": [
    "*"
  ],
  "RecoverIntermediateMasterClusterFilters": [
    "*"
  ],
  "OnFailureDetectionProcesses": [
    "echo 'Detected {failureType} on {failureCluster}. Affected replicas: {countSlaves}' >> /tmp/recovery.log"
  ],
  "PreGracefulTakeoverProcesses": [
    "echo 'Planned takeover about to take place on {failureCluster}. Master will switch to read_only' >> /tmp/recovery.log"
  ],
  "PreFailoverProcesses": [
    "echo 'PreFailoverProcesses' >> /tmp/recovery.log"
  ],
  "PostFailoverProcesses": [
  ],
  "PostUnsuccessfulFailoverProcesses": [],
  "PostMasterFailoverProcesses": [
    "echo 'PostMasterFailoverProcesses' >> /tmp/recovery.log" 
  ],
  "PostIntermediateMasterFailoverProcesses": [
    "echo 'Recovered from {failureType} on {failureCluster}. Failed: {failedHost}:{failedPort}; Successor: {successorHost}:{successorPort}' >> /tmp/recovery.log"
  ],
  "PostGracefulTakeoverProcesses": [
    "echo 'Planned takeover complete' >> /tmp/recovery.log"
  ],
  "CoMasterRecoveryMustPromoteOtherCoMaster": true,
  "DetachLostSlavesAfterMasterFailover": true,
  "ApplyMySQLPromotionAfterMasterFailover": true,
  "MasterFailoverDetachSlaveMasterHost": false,
  "MasterFailoverLostInstancesDowntimeMinutes": 0,
  "PostponeSlaveRecoveryOnLagMinutes": 0,
  "OSCIgnoreHostnameFilters": [],
  "GraphiteAddr": "",
  "GraphitePath": "",
  "GraphiteConvertHostnameDotsToUnderscores": true,
  "ConsulAddress": "",
  "ConsulAclToken": ""
}

10. 配置完成

啟動orchestrator:/etc/init.d/orchestrator start

訪問頁面,發現新實體:http://192.168.11.179:3000

     

實體拓撲圖:

 

Orchestrator自動恢復

故障檢測

  • Orchestrator在集群的主庫和所有從庫各啟動三個執行緒,每隔InstancePollSeconds重建連接,監控主庫和所有從庫複製是否正常;

  • 當檢測到主庫故障時,會通過從庫的連接查詢複製關係是否正常,如果主庫故障且所有從庫複製關係異常(不能連接到從庫或IO Thread異常),判定主庫故障(二次確認)

  • 呼叫OnFailureDetectionProcesses鉤子函式

  • 配置的MySQLConnectionLifetimeSeconds不小於InstancePollSeconds,避免間隔時間內資料庫沒有執行緒監控;

故障自動恢復  

  • 當檢測到主庫故障(DeadMaster)後,根據RecoveryPeriodBlockSeconds設置集群故障ack時間間隔,呼叫PreFailoverProcesses函式,如果呼叫成功(exit status 0),繼續執行否則退出故障切換;

    註意:當集群再次發生故障後,會檢查上次故障和當前故障的時間間隔,如果小於設置RecoveryPeriodBlockSeconds值,需要確認上次故障切換,否則會阻塞當前的故障切換;orchestrator-client -c ack-cluster-recoveries -a cluster01 -r ‘ack cluster01’或者通過WEB界面確認恢復:

  • 檢查可連接從庫的優先級(prefer、neutral、prefer_not、must_not)、downtime狀態、比較執行到的relay log位置,選舉新主

  • 重新配置複製關係,其他從庫執行ChangeMasterTo命令到新主

  • 提升新主

    • 原主begin-downtime(MasterFailoverLostInstancesDowntimeMinutes),檢查是否設置FailMasterPromotionIfSQLThreadNotUpToDate:

    • 如果設置為0則立即執行故障切換,不需要檢查新主是否應用完成relay log,在選舉的新主執行stop slave,RESET SLAVE ALL,read-only=0;這種場景下,可能則會造成資料丟失;

    • 如果設置為1則檢查選舉的新主是否應用完成relay log,如果未應用完成則故障切換失敗退出(如果DelayMasterPromotionIfSQLThreadNotUpToDate設置為true,會等待提升的新主應用完成relay log),這種場景下不會有資料丟失但是切換流程進行到一半退出,拓撲圖如下:     

  • 嘗試故障主庫的維護(RecoverDeadMaster),read-only=1

  • 呼叫PostMasterFailoverProcesses鉤子函式

  • 更新集群別名等操作

切換成功後實體拓撲圖

MyData優化

    • 由於原生Orchestrator在故障切換時存在的缺陷,MyData在這裡做了優化,使其支持了對於其管理的不同集群實體支持不同的切換方式,並新增引數豐富切換流程

    • failoverSlaveLagThreshold:主庫故障後首先檢查所有從庫的延遲,如果延遲均大於配置值,則不會切換

    • failoverWaitSlaveApplyTimeout:配置時間內,迴圈檢測從庫relay log應用是否完成,如果relay log應用完成,則立即切換,否則等待超時後再立即執行切換

    • slaveApplyOptimize:配置為true,迴圈檢測從庫relay log應用是否完成時,會檢查並修改所有從庫的配置引數(sync_binlog = 0、innodb_flush_log_at_trx_commit = 0、slave_parallel_workers = 16、long_query_time=100等),當應用relay log完成後再還原引數配置

    • Orchestrator優雅恢復

      • 通過執行命令或呼叫接口對MySQL資料庫複製關係調整

        curl -s http://192.168.11.179:3000/api/graceful-master-takeover/cluster01/192.168.11.176/22222
      • 或到管理節點192.168.11.179執行:

        orchestrator-client -c graceful-master-takeover -alias cluster01 -s 192.168.11.176: 22222
    • 切換流程:

      • 首先將其他從庫切換到指定主庫,Stopped replication,ChangeMasterTo,Started replication

      • 呼叫鉤子函式PreGracefulTakeoverProcesses,設置原主read_only停止寫入,同樣只有傳回0才能正常切換

      • 迴圈獲取集群實體信息,主要目的是檢查新主是否應用完成relay log

      • 呼叫鉤子函式OnFailureDetectionProcesses

      • 呼叫鉤子函式PreFailoverProcesses,同樣傳回非0退出切換

      • 在指定的新主執行STOP SLAVE, RESET SLAVE ALL, read-only=0

      • 呼叫PostMasterFailoverProcesses

      • 更新集群別名,在原主執行read-only=1

      • 原主執行ChangeMasterTo,將原主庫做為新主從庫,註意這裡沒有start slave

      • 呼叫鉤子函式PostGracefulTakeoverProcesses

總結

Orchestrator功能強大,能適應多種恢復場景,通過呼叫WEB接口和命令orchestrator-client能完成非常多的功能,這裡僅簡單介紹了常用的兩種場景;同時也可以看到其中部分功能需要修改完善,大家在使用過程中多關註其在Github上的更新。

雲和恩墨MySQL整體解決方案MyData基於Orchestrator進行了優化,保障了資料庫高可用的實現。

關於MyData

  • MyData是雲和恩墨自主研發的,針對MySQL資料庫提供高可用、高可靠、高安全性和易於使用的整體解決方案。MyData融合了雲和恩墨資深資料庫工程師的經驗和最佳實踐,來幫助客戶快速構建高可用的資料庫集群環境,保證了MySQL資料庫運行環境符合企業級資料庫的要求,幫助客戶提高快速交付的能力。

  • 雲和恩墨對MyData提供專業、靈動的端到端服務,涵蓋規劃設計、建設實施、運營管理和優化提升四個階段,為客戶構建安全、連續、高效和穩定的資料環境。

  • MyData目前已經在政府和金融行業擁有多個最佳實踐的案例,致力於為企業提供開展開源資料庫一體化的解決方案。

赞(0)

分享創造快樂