自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

AWS Aurora 數(shù)據(jù)庫 Failover 處理方案

數(shù)據(jù)庫 其他數(shù)據(jù)庫
在 Failover 過程中, 僅影響當(dāng)前活躍連接在數(shù)據(jù)庫重啟過程中對應(yīng)的讀/寫業(yè)務(wù),徹底消除 Failover 過程 DNS 帶來的read-only異常、也避免了 failover 后的連接傾斜現(xiàn)象,最小化的處理數(shù)據(jù)庫 failover 對應(yīng)用程序造成的影響。

Aurora簡述

Amazon Aurora 是亞馬遜自研的云原生數(shù)據(jù)庫,除兼容性、性能、擴展性外,它在設(shè)計之初,就以極致的可用性作為目標(biāo),盡可能減少故障對應(yīng)用程序的影響。

Amazon Aurora 在故障恢復(fù)方面的設(shè)計理念主要包括:

  1. 1. 能在較大范圍故障時仍然提供服務(wù):跨3個可用區(qū)的6備份存儲使它在一個可用區(qū)和另一個額外備份發(fā)生故障時仍能提供服務(wù);跨區(qū)域的全球數(shù)據(jù)庫能在主區(qū)域發(fā)生故障時快速切換到從區(qū)域;
  2. 2. 加快故障恢復(fù)的速度:將數(shù)據(jù)拆分成10 GB 粒度存儲單元使單個存儲單元能在秒級別恢復(fù);通過分布式存儲進行并行恢復(fù)等;快速找到健康計算節(jié)點先進行節(jié)點替換來使整個集群盡快提供服務(wù)。

圖片

Amazon Aurora 的架構(gòu)示意圖如上所示,僅有Primary RW(Read/Write) DB一個主節(jié)點用于處理寫請求,而其余的則為從節(jié)點Secondary RO(Read-Only) DB用于處理讀請求,在其論文中指出Secondary RO DB可以多達15個。( Aurora論文翻譯版本 )

Aurora有多主架構(gòu)嗎?如果是多主架構(gòu)會怎樣?

它們以端點 cluster endpoint 的形式對外提供服務(wù),用戶可以通過讀寫端點來訪問 Aurora 寫節(jié)點;通過只讀端點訪問 Aurora 讀節(jié)點。

這里的只讀端點只有一個,我們在應(yīng)用程序中的配置也只有一個,但并不表示我們只有一個只讀實例。

只讀端點下面可以掛載多個實例,通過 Route53(高度可用和可擴展的云托管域名系統(tǒng) (DNS) 服務(wù)) 進行負載輪訓(xùn)到不同的只讀節(jié)點實例。

Failover介紹

在 Amazon Aurora 中,F(xiàn)ailover 是指在主節(jié)點不可用時,自動或手動的將一個從節(jié)點提升為新的主節(jié)點的過程。

Failover 通常發(fā)生在以下情況:

主節(jié)點故障:如果主節(jié)點發(fā)生故障或停止服務(wù),Amazon Aurora 將自動將一個從節(jié)點提升為新的主節(jié)點,以確保數(shù)據(jù)庫的高可用性和容錯性。

可用區(qū)故障:如果主節(jié)點所在的可用區(qū)發(fā)生故障,Amazon Aurora 將自動將一個在其他可用區(qū)中的從節(jié)點提升為新的主節(jié)點。

手動干預(yù):如果需要執(zhí)行主節(jié)點的計劃維護或升級操作,可以手動將一個從節(jié)點提升為新的主節(jié)點,以確保數(shù)據(jù)庫的可用性和穩(wěn)定性。

當(dāng)寫節(jié)點發(fā)生故障時,Aurora 會進行如下的 Failover 過程:

1. 根據(jù)不同節(jié)點 failover 優(yōu)先級和復(fù)制延遲來選擇一個讀節(jié)點,將其提升成新的寫節(jié)點。因為該節(jié)點角色發(fā)生切換,需要重啟該節(jié)點。

2. 嘗試恢復(fù)原來的寫節(jié)點并讓它成為新的讀節(jié)點。這里也會涉及到節(jié)點重啟。

3. 待新的寫節(jié)點重啟成功以后,定位讀寫端點指向新的寫節(jié)點。這里涉及到域名的更新,依賴于 Route53 的實現(xiàn)。

4. 待新的讀節(jié)點重啟成功以后,定位只讀端點指向新的讀節(jié)點。這里同樣涉及到域名更新,依賴于 Route53 的實現(xiàn)。

AWS在控制臺提供了手動觸發(fā)failover的操作,我們可以通過觀測 Event 事件來查看 failover 過程中 Aurora 的讀寫節(jié)點究竟發(fā)生了哪些操作。

以一寫一讀的集群為例,在控制臺點擊 failover,可以觀測并整理出如下事件。

圖片

并繪制出事件時間圖

圖片

整個集群 failover 過程在29秒完成,其中,新的寫節(jié)點重啟成功用了7秒,新的寫節(jié)點在7秒以后就可以接受請求。

由于用戶訪問 Aurora 是利用域名的方式(Aurora 的讀寫域名和只讀域名),新寫節(jié)點啟動后需要更新域名,而域名更新需要一定的時間,所以應(yīng)用程序在數(shù)據(jù)庫實例可用到 DNS 更新完成這個時間段內(nèi)通過域名的方式連接 Aurora 集群時會發(fā)生連接錯亂的現(xiàn)象。

在DNS發(fā)生切換前,使用寫域名會連接到新讀庫上、使用讀域名會連接到新寫庫上。而這種情況會對應(yīng)用程序產(chǎn)生較大影響~~~

Failover對應(yīng)用程序的影響

我們分別使用Maria和AWS驅(qū)動做了測試。

這里我們使用當(dāng)前自身中間件版本的 ORM (基于 Mybatis 的封裝)和 Maria驅(qū)動,分析每個階段對程序的讀寫影響。

圖片

階段一

這個階段還未開始觸發(fā)failover,讀寫一切正常。

階段二

這個階段讀庫開始并正在重啟中,寫庫正常,對于寫庫的操作一切正常。

讀庫連接池狀態(tài): RO - Pool Status: Active: 0, Idle: 0, Total: 0, Waiting: 1

寫庫連接池狀態(tài): WR - Pool Status: Active: 1, Idle: 1, Total: 2, Waiting: 0

DEBUG級別日志:Connection refused (Connection refused)- 補充讀庫連接

對于讀庫的操作則會發(fā)生慢接口(queryTime > 業(yè)務(wù)sql執(zhí)行時間 + 階段二 + 階段三)。但這并不會意味著一定會產(chǎn)生ERROR異常,具體要看連接參數(shù)connection-timeout設(shè)置和restart的過程時長。

connection-timeout > restart

會有長查詢,但不會有ERROR級別異常。因為會在restart成功后正常建立TCP連接。

在這個過程中,Hikari連接池會做很多事情。

首先,這個階段連接池內(nèi)的連接都是一個time_wait狀態(tài)的,獲取連接時,這個連接如果空閑超出500ms,會在連接存活檢測失效,如果空閑在500ms內(nèi),會在執(zhí)行請求時立即得到連接關(guān)閉的狀態(tài)。

不管哪種此時連接池都會把它關(guān)閉并從維護的池中清理,直到把維護的連接都嘗試并清理個遍,然后嘗試創(chuàng)建新的連接進行補充。

如果此時我們開啟DEBUG日志的話會看到大量Connection refused (Connection refused)debug級別日志,只要restart時間在connection-timeout的范圍內(nèi),也就無所謂了,大不了就查詢時間長一些。

connection-timeout < restart

這時是會真的報ERROR級別的錯誤了

Cause: java.sql.SQLTransientConnectionException: single:RO - Connection is not available, request timed out after 30005ms.

階段三

主從數(shù)據(jù)庫全部不可用

寫庫也會進入讀庫的上個階段

階段四

讀庫連接池逐漸補充、讀請求正常

[single:RO connection adder] DEBUG com.zaxxer.hikari.pool.HikariPool - single:RO - Added connection org.mariadb.jdbc.MariaDbConnection@515740ab

讀庫連接池狀態(tài): RO - Pool Status: Active: 1, Idle: 1, Total: 2, Waiting: 0

注意: 此時DNS并未發(fā)生切換,補充進來的讀庫連接實際上是連接到老的讀庫上(新的寫庫)。

階段五

寫庫連接池逐漸補充、寫請求發(fā)生 --read-only異常!?。?/p>

[single:WR connection adder] DEBUG com.zaxxer.hikari.pool.HikariPool - single:WR - Added connection org.mariadb.jdbc.MariaDbConnection@2ca547c0

寫庫連接池狀態(tài): WR - Pool Status: Active: 1, Idle: 1, Total: 1, Waiting: 0

注意: 此時DNS并未發(fā)生切換,補充進來的寫庫連接實際上是連接到老的寫庫上(新的讀庫)。

階段六

連接池狀態(tài)

RO - Pool Status: Active: 0, Idle: 2, Total: 2, Waiting: 0

WR - Pool Status: Active: 1, Idle: 2, Total: 3, Waiting: 0

應(yīng)用異常日志

15:36:55.030 [http-nio-8080-exec-7] ERROR o.a.c.c.C.[.[.[.[dispatcherServlet] - Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.jdbc.UncategorizedSQLException: 
### Error updating database.  Cause: java.sql.SQLException: (cnotallow=5) The MySQL server is running with the --read-only option so it cannot execute this statement
### The error may exist in file [/sample-single/target/classes/mapper/StatusMapper.xml]
### The error may involve sample.orm.single.mapper.StatusMapper.longUpdate-Inline
### The error occurred while setting parameters

階段七

  1. 1. 讀請求正常
  2. 2. 寫請求持續(xù) read-only,直到連接生命周期結(jié)束(默認30分鐘)

。。。

很顯然、30分鐘的寫業(yè)務(wù)不可用是不可接受的……

如何應(yīng)對數(shù)據(jù)庫的Failover

通常情況下,Aurora 的 failover 通常能在30~60秒左右內(nèi)完成,對應(yīng)用程序產(chǎn)生較低影響。

那么,是否有可能進一步加快 Aurora failover 的速度呢?實現(xiàn)部分會重點介紹如何在 Aurora 進行故障恢復(fù)的時候避免或者減少 DNS 的影響,從而加快故障切換速度。

控制客戶端 DNS TTL 的時間

檢查客戶端是否緩存了DNS及設(shè)置時間,如果設(shè)置較久的話,可以考慮將客戶端的 DNS 的 TTL 調(diào)小,但這并不能消除DNS切換帶來的影響。

數(shù)據(jù)庫實例的底層 IP 地址在故障轉(zhuǎn)移完成后可能會發(fā)生變化,也就是說如果我在故障轉(zhuǎn)移過程中建立連接還是會有出錯的可能性。

使用 RDS Proxy

RDS Proxy 是基于 Aurora/RDS 之上提供的一個代理層,它有三個特性:

1. 連接池能夠?qū)崿F(xiàn)連接的多路復(fù)用,如果應(yīng)用對數(shù)據(jù)庫的并發(fā)請求比較多,直接打到 Aurora 數(shù)據(jù)庫上會耗費很多資源??梢允褂?RDS Proxy 來實現(xiàn)連接復(fù)用,支持更多的并發(fā)應(yīng)用,并減少新建連接的需要。

2. 增強的安全性,如果不希望直接把底層數(shù)據(jù)庫的密碼直接暴露,可以使用 RDS Proxy,通過使 RDS Proxy 訪問 Secrets Manager 里的密碼來增強安全性。

3. 快速的故障恢復(fù)時間,RDS Proxy 避開了 Aurora 發(fā)生故障切換時節(jié)點切換帶來的域名 DNS 記錄更新的問題,用戶通過連接 RDS Proxy 可以避免域名更新的時間消耗。

AWS 的另一個產(chǎn)品,據(jù)說會有SQL上的性能損耗,未使用、未調(diào)研、未測試。

AWS智能驅(qū)動

智能驅(qū)動在連接到 Aurora 集群時,會拿到整個集群的拓撲和各個節(jié)點的角色信息(是寫節(jié)點還是讀節(jié)點)維持在緩存中。

有了這個拓撲,在節(jié)點發(fā)生變化時,就可以快速拿到變化的節(jié)點的角色信息,而無需再依賴的 DNS 的解析。

圖片

AWS 官方圖

上圖是AWS智能驅(qū)動自身的邏輯示意,應(yīng)用程序連接到它時,會維護一個邏輯的連接和物理的連接。

比如現(xiàn)在的寫節(jié)點是 C,但同時它的拓撲緩存中會存放著節(jié)點 A 和 B 的信息,這樣如果節(jié)點 C 發(fā)生了故障,能夠及時檢測并將物理連接切換到 A 或 B 節(jié)點(取決于 Aurora 決定 failover 到哪個節(jié)點)而邏輯連接是保持不變的。

智能驅(qū)動與 MySQL 的普通驅(qū)動使用方法是一樣的,您只需要更換驅(qū)動,并將連接字符串更換為如下格式即可。

注意這里的 url 的字符串前面是 jdbc:mysql:aws。缺省情況下,故障切換的能力是開啟的,也可以通過參數(shù)調(diào)整的方式進行關(guān)閉。

jdbc:mysql:aws://集群名稱.集群id.us-east-2.rds.amazonaws.com:3306/數(shù)據(jù)庫名?useSSL=false&characterEncoding=utf-8

在對AWS智能驅(qū)動實驗中,failover這塊表現(xiàn)甚好,查看其failover代碼實現(xiàn),發(fā)現(xiàn)其為每個連接綁定了一套插件執(zhí)行鏈,其中就有failover插件。

圖片

AWS 官方圖

插件鏈的執(zhí)行必然會對SQL帶來點性能上的損失,為了能夠正常failover,這點損失也能接受。

查看其版本變化和ISSUE、嗯…… 很活躍。

中間件的處理方式

AWS是自己實現(xiàn)了JDBC的Connection,為每一個連接綁定了插件機制,在每個業(yè)務(wù)SQL執(zhí)行時檢測拓普變化,決定是否替換掉真實的物理連接,參考上上圖。

而我們使用Maria驅(qū)動每個創(chuàng)建的都是真實物理連接,如果要在物理連接上再抽象邏輯連接的話,工作量和實現(xiàn)都還是挺復(fù)雜的。

第一版:等待DNS切換的實現(xiàn)方案

圖片

在應(yīng)用程序中開啟一個線程每隔20s去拓普表中檢查當(dāng)前集群的寫節(jié)點是否發(fā)生變化,因為DNS切換的時間大概就是20s左右。

SELECT SERVER_ID, SESSION_ID, LAST_UPDATE_TIMESTAMP, REPLICA_LAG_IN_MILLISECONDS
FROM information_schema.replica_host_status
WHERE time_to_sec(timediff(now(), LAST_UPDATE_TIMESTAMP)) <= 300

圖片

當(dāng)檢測到集群拓普發(fā)生變化時,獲取集群主節(jié)點端點HOST和當(dāng)前集群寫端點域名進行探測,當(dāng)兩個端點指向相同IP時,認為DNS切換完成,發(fā)出重建數(shù)據(jù)源事件,進行數(shù)據(jù)源重建。(寫節(jié)點DNS切換基本維持在20s左右)

我們看下failover過程中DNS探測解析的日志(此過程和上圖不是在同一個failover中搜集的,時間會有偏差)

while true; do
  /bin/echo 'infra-test-cluster.cluster-cbot6qvorv5g   : ' $(date +%T) $(nslookup infra-test-cluster.rds.amazonaws.com | grep Address | grep -v '#53')
  /bin/echo 'infra-test-cluster.cluster-ro-cbot6qvorv5g: ' $(date +%T) $(nslookup infra-test-cluster.rds.amazonaws.com | grep Address | grep -v '#53')
  /bin/echo '---------------------------------------'
  sleep 0.5 # 0.5 second
done

===============================================================================================================================================================================================
infra-test-cluster.cluster-cbot6qvorv5g   :  16:37:33 Address: 10.57.51.213
infra-test-cluster.cluster-ro-cbot6qvorv5g:  16:37:33 Address: 10.57.52.67
---------------------------------------
infra-test-cluster.cluster-cbot6qvorv5g   :  16:37:34 Address: 10.57.51.213
infra-test-cluster.cluster-ro-cbot6qvorv5g:  16:37:34 Address: 10.57.52.67
---------------------------------------
infra-test-cluster.cluster-cbot6qvorv5g   :  16:37:35 Address: 10.57.52.67
infra-test-cluster.cluster-ro-cbot6qvorv5g:  16:37:35 Address: 10.57.52.67
---------------------------------------
中間相同省略……
---------------------------------------
infra-test-cluster.cluster-cbot6qvorv5g   :  16:38:07 Address: 10.57.52.67
infra-test-cluster.cluster-ro-cbot6qvorv5g:  16:38:07 Address: 10.57.52.67
---------------------------------------
infra-test-cluster.cluster-cbot6qvorv5g   :  16:38:08 Address: 10.57.52.67
infra-test-cluster.cluster-ro-cbot6qvorv5g:  16:38:13 Address: 10.57.51.213
---------------------------------------

failover 過程中域名DNS解析總結(jié)

1. 【寫域名】轉(zhuǎn)移到【老讀庫】 -- 16:37:35

2. 此時間段讀寫域名都解析到【老讀庫】(后續(xù)晉升為新寫庫) -- ----

3. 【讀域名】轉(zhuǎn)移到【老寫庫】(后續(xù)降級為新讀庫) -- 16:38:13

此方案的問題:

  1. 1. DNS完成切換前會有寫業(yè)務(wù)的 read-only報錯,持續(xù)在階段五,時間10~20s,主要看老讀庫重啟時長。
  2. 2. 從上面DNS探測的結(jié)果可以看出,會有持續(xù)較長一個階段讀寫域名解析到同一個實例上(老讀庫=新寫庫)。當(dāng)探測到寫庫域名切換時發(fā)起數(shù)據(jù)源重建,此時創(chuàng)建的讀連接會連接到新寫庫上。盡管不會對業(yè)務(wù)產(chǎn)生影響,但是讀寫分離的功能會持續(xù)30min失效。

圖片

如果是由于瞬時流量造成的寫庫故障發(fā)生failover,這樣切換到新寫庫上的話,除了正常的寫流量還會有所有的讀流量涌入,這樣將更快的把寫庫打垮,然后繼續(xù)failover……

那再把讀庫域名的切換加入到探測過程中呢?等待讀寫域名指向全部穩(wěn)定后再發(fā)起數(shù)據(jù)源重建事件怎樣?

首先,read-only的報錯時長會拉長,因為要同時等待讀寫域名的切換完成。

其次,如果我們只讀端點掛載多個讀實例的話,讀庫域名會在 Rout53 下每 5~30s 進行輪訓(xùn),固定不下來不好作為 DNS 切換完成的依據(jù)。

可以對只讀端點域名進行多次探測,當(dāng)發(fā)現(xiàn)輪訓(xùn)結(jié)束后的IP數(shù)量等同于讀庫數(shù)量時認為讀庫DNS切換完成。這個時間就太長了,并且還不確定是不是采用的輪詢算法。

此時,又想起了AWS智能驅(qū)動…… 不幸的是它也沒有解決上述問題(上圖AWS-1.1.5版本測試結(jié)果)

第二版:依賴拓普結(jié)構(gòu)創(chuàng)建連接

上面看AWS故障轉(zhuǎn)移模塊代碼的時候發(fā)現(xiàn),當(dāng)發(fā)生故障轉(zhuǎn)移時,邏輯連接不變,物理連接會通過拓普中的實例端點進行連接替換。

要在Maria的連接中按照此方案實現(xiàn)的話,工作量太大、實現(xiàn)太復(fù)雜。

我們使用的是HikariCP連接池管理的鏈接生命周期,那如果我們在連接池創(chuàng)建連接時讓它按照我們給定的拓普去連接呢?

這樣的話,我們不僅解除了對DNS的解析依賴、還可以按照指定算法對讀庫進行連接負載,同時還可以把故障影響范圍控制在數(shù)據(jù)庫實例重啟的時間范圍內(nèi)了!?。?/p>

在連接池創(chuàng)建連接前,我們通過外部配置給定的集群讀/寫端點獲取當(dāng)前集群拓普結(jié)構(gòu),在連接池創(chuàng)建連接的時候,寫庫連接我們分配主端點、從庫連接我們按照自己的分配算法(輪詢),將分配后的實例端點給到連接池,讓它按照我們給定的實例端點進行連接的創(chuàng)建。

圖片

其中SwitchHostDatasource需要自己實現(xiàn)并給到Hikari,讓連接池使用我們提供的Datasource進行連接的創(chuàng)建和維護。

經(jīng)驗證,在 Failover 過程中, 僅影響當(dāng)前活躍連接在數(shù)據(jù)庫重啟過程中對應(yīng)的讀/寫業(yè)務(wù),徹底消除 Failover 過程 DNS 帶來的read-only異常、也避免了 failover 后的連接傾斜現(xiàn)象,最小化的處理數(shù)據(jù)庫 failover 對應(yīng)用程序造成的影響。

巨人的肩膀:

https://aws.amazon.com/cn/blogs/china/be-vigilant-in-times-of-peace-amazon-aurora-fault-recovery-reduces-the-impact-of-dns-switching-on-applications/

責(zé)任編輯:武曉燕 來源: 艾小仙
相關(guān)推薦

2015-01-13 10:10:01

亞馬遜Aurora云數(shù)據(jù)庫

2014-12-12 16:53:07

AWS關(guān)系型數(shù)據(jù)庫Aurora系統(tǒng)

2015-10-14 09:49:42

AWSAzure云數(shù)據(jù)庫

2014-11-14 09:19:23

AWSAmazon Auro

2014-11-13 12:55:11

亞馬遜

2019-04-10 09:00:23

AWSOracle數(shù)據(jù)庫

2017-12-02 12:25:07

AWS數(shù)據(jù)庫

2022-04-11 10:20:31

數(shù)據(jù)庫云原生數(shù)據(jù)

2014-02-14 09:22:36

AWSOracle云數(shù)據(jù)庫

2014-12-08 10:08:45

AWSAWS數(shù)據(jù)庫MongoDB

2016-01-27 17:43:17

AWS技術(shù)峰會AWS Summit2

2021-12-02 10:39:43

自動駕駛數(shù)據(jù)汽車

2010-06-01 17:14:28

2010-05-07 13:28:43

Oracle數(shù)據(jù)庫

2018-05-02 08:48:58

Raid存儲MySQL

2015-03-11 10:01:31

2015-03-12 10:26:41

2015-01-06 09:41:25

AWS數(shù)據(jù)庫部署數(shù)據(jù)庫監(jiān)控

2011-05-26 13:36:40

Oracle數(shù)據(jù)庫時間處理

2011-04-07 15:47:28

MySQL數(shù)據(jù)庫
點贊
收藏

51CTO技術(shù)棧公眾號