AWS是怎麼改寫 MySQL的

2022-10-11 08:45:11 字數 3823 閱讀 2410

五倍吞吐量的提公升,跨可用區的六副本,低於一分鐘的宕機恢復,相容 mysql協議,這是 aws 推出 aurora 資料庫時給出的資料。

這種量級的提公升不可能是小修小補,大都是在架構上有了變革性的突破才能達到,坊間流傳了很多aurora 效能提公升的秘密,在 sigmod'17 上amazon 終於自己發了一篇**介紹了在雲環境下如何重新打造資料庫這種傳統軟體。很多的傳統軟體都可以看一下上雲是不是只是裝乙個軟體那麼簡單。

資料永續性

儘管 aurora 的效能資料很亮眼,但對於資料庫來說最基本的要求還是一旦資料寫入成功就不能丟,資料的永續性才是第一位的。多副本是解決資料永續性的常用辦法,aws 採用了基於 quorum 投票的協議來管理副本。簡單說就是如果有 n 個副本,則一次寫資料要求至少寫入(n/2)+1 個節點才算寫入成功,剩下的節點通過相互之間的一致性協議可以達到共同的狀態,而讀資料則要求至少從 n/2 個節點中讀出相同的資料才能決定哪個資料是最新的。(www.alauda.cn)

對於乙個 3 副本的 quorum 系統,讀寫的 quorum 數都是 2 ,這也是乙個比較常見的高可用系統選擇的 quorum 數。但是這個副本數放在大規模多組戶的系統裡是不能保證資料的永續性的。因為在大規模系統中,節點出問題是每時每刻都會發生的,如果只有三副本的話,基本上每時每刻都會有乙個使用者的系統處在 2/3 的健康狀態。aws 的 3 副本是分布在 3 個不同的可用區的,如果乙個可用區出了故障,那麼所有的資料庫副本就會變成 2/3 的健康狀態,這種情況下任意乙個機器的故障都會導致乙個使用者的 quorum 健康數變為 1/3,這時候就沒有辦法判斷資料是否一致了。

所以 aurora 採用的是六副本,每個可用區兩副本。這種架構可以保證寫入操作可以容忍乙個可用區不可用的情況 4/6,而讀資料可以容忍乙個可用區外加一台機器不可用的情況 3/6。一旦出現了乙個可用區加一台機器不可用的 3/6 情況,寫資料會被禁止,但是由於讀資料可以進行可以很快的根據讀出的資料再恢復出乙個副本達到 4/6 狀態恢復寫入。

資料分片

現在來想一下出現了乙個 az 加一台機器掛掉的情況,這時我們需要重建乙個副本,那麼重建的時間就取決於資料庫副本檔案有多大,隨著資料庫增長,恢復時間也會線性增加。這個對乙個發展越來越好的業務是不能接受的,所以需要盡可能降低資料恢復時間。恢復時間過長還會帶來另乙個隱患就是在恢復的過程中如果又有乙個機器故障,那麼資料就沒辦法直接通過其他副本來恢復了,而恢復時間越長這個風險越大。從 cap 的角度來看  aurora 作為乙個利用分布式儲存的資料庫是選擇了 cp,但是如果可用性出了問題能在極短的時間恢復,那麼從實際使用角度也就和 cap 系統差不多了。 

乙個直接的做法就是把副本分片,這樣乙個副本就可以散落在多台機器,這樣一台機器掛的情況下我們就不需要恢復完整的副本,只需要恢復機器上的分片就可以。另一方面由於資料進行了分片,讀資料的時候也可以利用多台主機的 io 頻寬,對效能也有提公升。aws 採用了 10g 的分片大小,這樣在萬兆網路的內網環境下,恢復乙個分片可以在 10s 內完成,這樣在比較極端的 1az+1 出故障的情況下,可以保證 10s 內恢復資料庫讀寫。

這種資料分片的方式保證了資料庫有很高的可用性,從運維角度來說就可以對這個系統進行rolling update 了。比如想要公升級底層的作業系統和軟體,可以直接把機器下線進行公升級,上面的分片都會很快在別的機器上進行重建,然後再把機器加回集群公升級下乙個。發現某台機器硬體有異常也不需要做手工的資料遷移,直接把機器下線送修。另外當出現資料熱點的時候也可以直接將這個熱點機器的其他分片標記為不可用把分片遷移走,來避免某乙個使用者的行為造成其他使用者的效能下降。這些都是分片帶來的好處。

副本的***

前面說了多副本帶來的資料持久和高可用,但是多副本並不是沒有代價的。本來磁碟 io 的速度就慢,多個副本之間即使是並行的寫入操作,latency 也會變成最慢的節點的 latency,隨著副本數的增多,抖動會變得更大。另外在雲環境下的資料庫和傳統環境下資料庫很重要的一點不同就是計算和儲存是分離的,這種情況下讀資料可以從本地快取中拿,而寫資料就需要網路 io,由於儲存分散在了多台機器上可以並行利用磁碟頻寬,瓶頸就來到了網路。

而 mysql 自己的一些 io 機制主要是針對本地磁碟設計的,很多優化方法並不適用於網路儲存,此外 mysql 自己的一些事務和故障恢復的機制,會造成寫放大的問題。來看一下 mysqlmirror 機制下的 io 流程:

可以看到資料庫一次寫入除了要把資料寫入還有 log, binlog,double-write,frm-file 這些東西要寫入,而且需要在 master 上完成後才能再去 mirror 上執行同樣的過程,等到 mirror 完成後一次請求才能結束。如果直接用 mysql 的 mirror 機制那麼上面提到的 6 副本系統實際上寫入需要滿足 6/6 才能成功,延遲會極大的加大。如果 aws 採用這種機制,吞吐量不降到六分之一就算萬幸了,更不要提五倍的提公升了。這大概也是 aws 想要自己搞資料庫的原因,那麼該怎麼搞呢?

log 即資料

要說 aws 比起 oracle(mysql 現在的爹)做 mysql 有什麼優勢的話那就是雖然資料庫我沒你們熟,但是底層的系統硬體我們都可以自己控制呀。看一下上面那張 io 流程圖,其實很多 log 都是怕底層儲存出問題,機器突然斷電造成資料不一致和考慮如何進行恢復才生成的。此外這裡的一些資料是有冗餘的,比如資料庫在寫入資料前都要先寫入 wal 再進行資料頁的寫入,至於為什麼要這麼做可以參考 《wal 是如何保證資料庫事務一致性的》,這裡只要知道通過 wal 我們是可以重建資料的,只是這樣做讀資料效率會比較低所以資料庫都會再寫一次完整資料到硬碟,保證讀的效率。

另外由於 mysql 自己本身不能更改儲存系統的功能,所以映象功能需要自己控制實現,所有的資料同步都要過 mysql 這個使用者層程式去控制,而這些同步的功能又會占用大量的資源開銷影響正常的讀寫操作,相當於每寫一次資料,資源開銷是原來的多倍。此外在故障恢復的時候 mysql 在啟動時需要話大量的時間對比日誌和實際資料狀態的差異,就行資料修復,這個過程也會導致故障恢復時間的延長。

aws 的解決方式就是既然wal 裡已經包含了所有的資料,那麼我就不同步其他的東西了,只同步 log 就可以了。mysql 去控制同步過程效率低,我底層的 ebs 自己就帶同步功能啊,根本不需要 mysql 再去控制,mysql 基本只需要老老實實的做 sql 相關的工作就可以了。資料庫的故障恢復,儲存系統可以自己進行資料恢復,mysql只需要把引擎啟動起來就可以了。總結來說就是 mysql 之前之所以慢是因為檔案系統有很多缺陷需要很多額外的功夫來保證資料寫入能成功,現在 aws 給了乙個及其完善的檔案系統,資料寫入了就能成功,斷電了也能自己恢復,還能自己做多副本,那麼 mysql 自己要做的事情就少了,效能自然也就上去了。現在的流程就簡化成了:

所有的 replica 節點不需要將資料寫入磁碟了,資料同步由底層的 ebs 系統來做。replica 節點只需要接收 primay 的 log 資訊來更新本地的快取和一些全域性的配置。primary 的寫入操作也不再需要各種各樣的 log 寫入,只需要把 wal 給底層儲存系統,儲存系統會自動的寫入到一定的 quorum 節點上。而有了這些 log,儲存系統會自動的去做 checkpoint, 備份和故障恢復,而且這些耗時的操作都是在後台默默的非同步執行的,不需要前台的 mysql 引擎。這樣寫入操作的 io 量和操作路徑都顯著變少了,aws 才能把 mysql 的效能在雲環境裡提公升那麼多。

再加上分片的儲存將磁碟 io 的壓力分散,讀寫效能都得到了顯著提公升,放兩張圖來感受一下:

mysql怎麼改utf mysql如何修改utf8

mysql修改utf8的方法 首先通過 show variables like character set 檢視mysql字符集 然後在mysql安裝目錄下找到my.ini檔案並修改 最後重啟mysql即可。推薦 mysql教程 mysql 5.7版本修改編碼為utf 8 首先通過 show var...

mysql怎麼改本地服務 怎麼設定本地伺服器路徑

回答數 104 被採納數 19 2017 01 13 18 12 16 俺又自己解決了 s 476 s 495 資料庫型別 dbtype mysql 資料庫使用者名稱 dbuser root 資料庫密碼 dbpass 17911 伺服器名,本地 dbserver localhost 資料庫名 dbn...

mysql資料庫姓名 怎麼改mysql資料庫的名字

改mysql資料庫名稱的方法 首先建立目標庫 然後獲取所有源庫的表名 最後按照相關命令乙個個修改,為 rename table srcdb.tablename to trgdb.tablename 改mysql資料庫名稱的方法 1 如果是myisam的話,只要修改data目錄下面的那個庫名的資料夾的...