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|bash
yum 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:22222
orchestrator管理節點: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 = ON
enforce_gtid_consistency = 1
binlog_format = ROW
log-bin =/data/mysql/data/mysql-bin
slave_preserve_commit_order=1
report_host = 192.168.11.175
master-info-repository = TABLE
log_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(4) NOT NULL,
`cluster_name` varchar(128) NOT NULL DEFAULT '',
`cluster_domain` varchar(128) NOT 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目前已經在政府和金融行業擁有多個最佳實踐的案例,致力於為企業提供開展開源資料庫一體化的解決方案。
朋友會在“發現-看一看”看到你“在看”的內容