MySQL - 擴充性 1 概述:人多力量未必大
我們應該接觸過或者聽說過資料庫的性能瓶頸問題。對于一個單機應用而言,提升資料庫性能的最快路徑就是氪金 - 買更高性能的資料庫伺服器,隻要錢到位,性能不是問題。
但是當系統性能增加到一定地步時,你會發現,原先花 3000 塊提升了 50% 的性能,現在花 30000 塊,才提升了不到 10%。
也就是說,我們花了錢,但沒有得到等價的性能提升,這個時候,我們就要考慮資料庫的可擴充性了。
要讨論 MySQL 的可擴充性,就要先明确可擴充性的定義。在此之前,我們先抛開 MySQL,專注于擴充性,搞清楚什麼是擴充性,才能更有針對性的去提高 MySQL 的擴充性。
1 什麼是可擴充性
我們常常把“可擴充性”、“高可用性”以及“性能”用作同義詞,但事實上它們是完全不同的。簡單來說,性能是響應時間,可用性是當機時間,而擴充性表明了當需要增加資源以執行更多工作時,系統能夠獲得等價的性能提升的能力。換種說法,可擴充性就是我們能夠盡可能的花費相同的資源提升等價的性能。而缺乏擴充能力的系統在達到收益遞減的轉折點後,将無法進一步增長。
容量是一個和可擴充性相關的概念。系統容量表示在一定時間内能夠完成的工作量。
容量和可擴充性并不依賴于性能。以高速公路上的汽車來類比的話:
性能是汽車的時速。
容量是車道乘以最大安全時速。
可擴充性就是在不減慢交通的情況下,能增加更多車和車道的程度。
在上面這個類比中,可擴充性依賴多個條件:換道設計是否合理、路上有多少車抛錨或發生事故、汽車行駛速度不同以及是否頻繁變換車道。但一般來說,和汽車的引擎是否強大無關。
這并不是說性能不重要,性能确實重要,隻是要注意的是,即使系統性能不是很高的系統也可以具備可擴充性。
從較高層次看,可擴充性就是能夠通過增加資源來提升容量的能力。
對于容量,我們可以簡單的認為是處理負載的能力,而從不同的角度考慮負載對我們優化擴充性很有幫助。
資料量
應用所能累計的資料量是可擴充性最普遍的挑戰,特别是對于現在的網際網路應用而言,因為從不删除資料。
使用者量
首先,即使每個使用者隻有少量的資料,但在累計到一定數量的使用者後,資料量也會開始不成比例的增長,且速度快過使用者數增長。其次,更多的使用者意味着要處理更多的事務,并且事務數可能和使用者數不成比例。最後,大量使用者也意味着更多複雜的查詢。
使用者活躍度
不是所有的使用者活躍度都相同,并且使用者活躍度也不總是不變的。如果使用者突然變得活躍,例如 github 給小團隊免費開放了私有化倉庫,那麼其對應的負載可能會明顯提升。要注意的是,使用者活躍度不僅僅指頁面浏覽數(PV),即使同樣的 PV,如果網站的某個需要執行大量查詢工作的功能變得更受歡迎,也可能導緻更多的工作。
相關資料集的大小
如果使用者間存在關系,應用可能需要在整個相關聯使用者群體上執行查詢和計算,這比處理一個個的使用者和使用者資料要複雜的多。
說了這麼多,隻是為了讓我們更好的了解可擴充性的讓我們用下面圖表來更明确的表達可擴充性。
假設有一個隻有一台伺服器的系統,并且能夠測量它的最大容量,如圖 1 所示:
圖1:一個隻有一台伺服器的系統
假設我們現在增加一台伺服器,系統的能力加倍,如圖 2 所示:
圖 2:一個線性擴充的系統增加一台伺服器獲得兩倍容量
圖 2 就是線性擴充。我們增加了一倍的伺服器,增加了一倍的容量。然而,理想是美好的,現實是骨感的。大部分系統并不是線性擴充的,而是如圖 3 所示的擴充方式:
圖 3:一個非線性擴充的系統
大部分系統都隻能以比線性擴充略低的擴充系數進行擴充。這就導緻,多數系統最終會達到一個最大吞吐量臨界點,超過這個點後增加投入可能反而會降低系統的吞吐量。
到這一步,大家對擴充性應該已經有一個較為清晰的概念了。在此基礎上,讓我們再深入一步:Amdahl 擴充 和 USL 擴充。
簡而言之,USL 說的是線下擴充的偏差可通過兩個因素來建立模型:
無法并發執行的一部分工作;
需要互動的另外一部分工作。
在對第一個因素繼續模組化後,就有了著名的(聽過這個著名嗎?)阿姆達爾定律(Amdahl)。第一個因素最終會導緻吞吐量趨于平緩。如果部分任務無法并行,那麼不管你如果分而治之,該任務至少需要串行部分的時間。這句話很重要,讓我們用一個栗子再簡單闡述下:
假設大家都做過韭菜煎蛋這道菜,我們做這道菜時,有幾個必要步驟:
切韭菜,耗時 t1;
打蛋液,耗時 t2;
開煎,耗時 t3;
就上面 3 個步驟而言,你可以在切韭菜的時候,讓你女票幫你打蛋液,也就是說 1、2 是可以并行的,但是我們能邊切菜邊煎嗎?或者邊打蛋液邊煎嗎?顯示是不行的。是以,步驟 3 和 1、2 是串行的。
這時候,我們就會發現,做韭菜煎蛋這個任務需要的時間 t 為:
t = t1 < t2 ? t1 + t3 : t2 + t3;
對第二個因素,需要互動的工作而言,互動就意味着内部節點間或者程序間的通信。這種通信的代價取決于通信信道的數量,而信道的數量将按照系統内工作者數量的二次方增長,是以最終開銷比帶來的收益增長的更快,這就是産生擴充性倒退的原因。由此和 Amdahl 定律,就得出了 USL。
圖 4 闡明了目前讨論的三個概念:線性擴充、Amdahl 擴充以及 USL 擴充。而大多數真實系統看起來更像 USL 曲線。
圖 4:線性擴充、Amdahl 擴充以及 USL 擴充定律
至此,關于擴充性的概念描述告一段落。接下來,我們回到正題,看看 MySQL 的擴充性如何規劃。
2 規劃可擴充性
什麼情況下需要擴充?,這是個值得我們牢記的問題。當我們提到系統的可擴充性時,一般隻有兩種情況:
剛開始規劃一個應用;
目前應用無法滿足增加的負載;
上述兩種情況,大多數情況下我們碰到的應該都是後者。具體表現為:
CPU 密集型變成 I/O 密集型;
并發查詢競争;
不斷增大的延遲;
如果是可擴充的應用,可以簡單地增加更多的伺服器來分擔負載。但如果是可擴充性比較差的,你就會發現 - 隻剩下提高可擴充性這一條路可走。
隻有一條路,那就且行且 996 吧!
走上了提升擴充性這條路,接下來的問題就是,如何提高可擴充性?這裡比較困難的部分是估算應用承擔的負載到底有多少?這個值不一定非常精确,但必須在一定的數量級範圍内。什麼?你問為什麼要在一定範圍内?不清楚敵人的火力,咱們是準備用高射炮打蚊子還是用大刀對機槍呢?
除此之外,為了能幫助我們更好的規劃可擴充性,咱們最好還能想清楚下面這個問題:
應用的核心功能完成了多少?很多可擴充性方案可能會導緻某些功能實作起來更加複雜。在核心功能沒完成前,問問自己,真的要走提升擴充性這條路嗎?換個說法,準備好迎接 996 了嗎?
3 為擴充赢得時間
程式員們理想的開發環境應該是:計劃先行、有足夠能夠一起戰鬥的同伴、有花不完的預算等等。但現實是:
boss:诶,小九啊,咱們系統提升下性能要多久啊?三天應該差不多了吧,最多不能超過一周,上次提升性能,小六一天就搞定了的。
小九:。。。卒
正常情況下,提升系統的擴充性的難度可能要比重構的難度還要大。是以,在你沒有完全把系統摸熟悉,或對擴充性還模糊的時候,千萬别給老闆說要提升系統的擴充性。
在老闆要求提升性能時,你要想盡一切辦法滿足他提升性能的需求,同時,要多想下如何提高系統的擴充性,為将來提升擴充性赢得時間。
可以通過以下工作先提升系統性能:
優化性能。很多時候可以通過一個簡單的改動來獲得明顯的性能提升。例如為表建立正确的索引,或從 MyISAM 切換到 InnoDB。再進一步,可以通過慢日志來分析。
購買性能更強的硬體。在應用早期,更新或增加伺服器可以顯著的提升系統性能,并且還能快速的完成。就像我們把伺服器從 1 台增加到 3 台,可能就能讓性能提升 100%,但是當我們的伺服器已經到達 100 台時,再從 100 增加到 300,這時候的複雜度和成本可能已經讓你心甘情願走上提升系統擴充性的道路上了。
總結
擴充性是當需要增加資源以執行更多工作時,系統能夠獲得等價的性能提升的能力。
不準确評估應用負載的擴充,都是耍流氓。
原文位址
https://www.cnblogs.com/BeiGuo-FengGuang/p/10681465.html