1. 程式人生 > >【經驗】GaussDB(for MySQL)效能優化 —— 日誌的“快遞驛站”

【經驗】GaussDB(for MySQL)效能優化 —— 日誌的“快遞驛站”

GaussDB(for MySQL)資料庫在寫入效能上,在業界同類產品中是最好的,這主要得益於GaussDB(for MySQL)在MySQL核心方面的諸多優化。其中有一項從“送快遞”得來靈感的優化——事務非同步提交,值得我們分析。

背景

我們先來看看MySQL 8.0的事務提交的大致流程

圖1 MySQL 8.0事務執行流程

以上流程,是MySQL8.0對WAL原則的一種實現,這個流程意味著,任何一個事務的提交,一定要完成write buffer和flush to disk流程。

然而那麼這個流程中,有一個問題:每個伺服器的CPU是有限的,伺服器能處理的Thread也是有上限的,那麼當我們的業務的併發數量,遠遠大於我們伺服器能並行處理的數量時,那麼後來的事務,只能等待前面的事務提交後才能被處理。在這之前,他們什麼也做不了。因此,在大併發場景下,如何進一步提升執行緒的使用率,是大併發事物寫入的一個關鍵。

靈感來源於生活

一個優化,並不是憑空想象出來的,有時候,往往來源於現實生活。下面,我們先來看看我們身邊,和事務提交流程非常類似的一個例子:快遞。

現在的快遞配送,一般一個快遞員會負責一片區域,快遞剛開始興起時,數量不多,那麼一個快遞員基本上可以在規定時間內完成配送。

圖2 過去的快遞配送

但是,隨著快遞數量越來越多,一個快遞員要在一個小區配送很長的時間,才能到下一個小區,常常導致了快遞員無法準時的配送。在這個問題的催動下,隨後,一個新的行業開始出現 – 快遞驛站。

圖3 現在的快遞配送

快遞的優化原理

接下來,讓我們來看下,快遞驛站究竟解決了什麼問題。

快遞的配送過程中,最耗時的,不是裝貨,不是卸貨,而是電話和等待。配送一個小區的時間,取決於這個最後一個來取快遞的人的時間,在最後一個人取完快遞錢,快遞員除了打電話,做不了其他任何事情(也沒有辦法通知下一個小區的人,因為最後一個人來取得時間是無法確定的)。那麼這個等待的時間,對於快遞員來說,就是一種浪費。

快遞驛站可以很大程度解決這個問題,快遞員到了以後,只需要將快遞卸貨,即可前往下一個小區,剩下的事情,就可以由驛站的人員來完成,大大提升了快遞員的配送效率。

分析

回過頭來,我們看看資料庫,如果把Transaction執行緒看做快遞員,儲存上的檔案看做取快遞的人,那麼我們會發現兩者有非常大的相似性。那麼我們可以像快遞配送優化那樣去優化事務的處理流程嗎?答案是可以的。

圖4 事務處理和快讀配送非常類似

根據快遞驛站的優化原理,我們知道,快遞驛站幫快遞員免去了等待客戶取貨的時間,那麼事務處理過程中,有沒有等待的過程呢?答案是有的,儲存的IO就是一個較長的等待。資料庫使用經驗豐富的開發人員來都知道,等待redo日誌寫入儲存的磁碟IO效能,很大程度上決定了資料庫的寫入效能。對於現代資料庫來說,尤其對於GaussDB(for MySQL)這樣計算於儲存分離的資料庫,儲存的IO耗時,在事務處理的總耗時中,佔據了不小的比例,雖然有log buffer的合併寫入,提升併發情況下的整體吞吐,但是如果在等待IO的這段時間中,這些執行緒能夠去做別的事情(例如處理等待中的其他事務)。那麼將會有進一步的效能提升。

GaussDB(for MySQL)的優化

既然找到了等待的點,那麼我們就可以像快遞配送的優化方法,為資料庫,也創造一個“快遞驛站”,讓“快遞驛站”來做等待的事情,而事務執行緒就可以去處理其他等待中的事務,讓CPU不會“閒下來”。

圖5 GaussDB(for MySQL)的“快遞驛站”

如圖5所示,GaussDB(for MySQL)當redo日誌的flush to disk動作完成後,即可進行事務提交,但是此時並不應答客戶端,而是直接處理下一個事務。同時使用少量”post comit worker執行緒”,來批量等待日誌寫入完成(等待的過程其實並不佔用CPU),並應答客戶端,這就可以讓“等待”和“下一個事務的處理”並行化,讓CPU“閒不下來”。

實際測試

圖6 Sysbench write only 模型下寫入效能測試

根據實際測試,在標準的sysbench寫入模型下,沒有使用Post Commit時,極限效能是35萬QPS左右,而使用Post commit後,可以到大42萬以上的QPS,提升了20%的寫入效能。

 

點選關注,第一時間瞭解華為雲新鮮技