天天看點

隊列理論在PostgreSQL寫WAL中的應用

隊列理論在我們生活中的應用随處可見,例如機場、海關、銀行甚至排隊買菜。可以說,隻要有排隊的地方,就可以應用隊列理論進行服務優化。



   在計算機領域的架構設計,性能診斷等地方使用隊列理論的案例也多不勝舉。曾經教育訓練的時候聽到過,有牛人可以在不了解具體技術的情況下僅憑隊列理論的知識就可以快速定位系統的瓶頸所在。拿一台伺服器來講,分為動态裝置和靜态裝置。CPU和IO子系統屬于動态裝置,RAM屬于靜态裝置,隊列理論隻對動态裝置适用。今天不打算介紹隊列理論的基礎知識,而想讨論一下隊列理論在PG資料庫對于寫WAL上的應用。



   一個系統的響應時間由兩部分決定,等待時間和服務時間。而這兩部分時間又受到到達速率和服務速度的影響。這是隊列最基本的因素。



   在PostgreSQL中,有一個參數叫做commit_delay,可以通過調整它在某些情況下來提升系統的吞吐量。按照官方文檔,commit_delay定義了一個組送出上司程序(group commit leader process)在調用XLogFlush中獲得鎖後,需要睡眠多少微秒來讓組送出跟随者程序(group commit followers)進行排隊,這樣其他事務的WAL也可以寫入到WAL buffer中,在下一次被喚醒時組送出上司者程序便可以一次重新整理多個事務的WAL到持久化的IO裝置中,進而可以提升系統的總吞吐量。



   那麼,這個參數的調整為什麼可以在某些情況下提升系統的吞吐量?對于WAL寫入來講,等待時間是指一個送出請求到達但還沒有被持久化到磁盤上的WAL段的時間,服務時間則是組送出上司者程序執行SYNC操作将WAL buffer持久到磁盤上WAL的時間。磁盤的響應時間在這裡是服務速度,而系統的并發度,機關時間内的commit請求數則為到達速率。這裡面有幾種情況:
           

1、當到達速率很低,也就是并發度很低的情況下,IO裝置的響應時間也就是服務速度雖然慢但能夠應付得過來,并不需要做任何調整。整體的響應時間基本上就是IO裝置的響應時間;

2、到達速率很低,也就是并發度很低的情況下,IO裝置的響應時間很快,更加不需要做任何調整。整體的響應時間基本上就是IO裝置的響應時間;

3、到達速率很高,系統并發度很高,IO子系統存在高延遲,

手機遊戲賬号轉讓平台

響應時間很長,服務速度很慢,很快就會造成需求積壓。如果一個需求一個需求處理,則需求積壓會越來越嚴重,事務延遲(等待時間)越來越長,導緻系統吞吐量急劇下降。這種情況下,我們可以合并需求,将多個需求打包一起處理,減少和慢速IO子系統的互動次數,系統吞吐量得以上升。如果難以了解,大家不妨想一下乘坐機場擺渡車的情況。但是也要考慮不能合并過多需求,否則對于每個單一需求來講,延遲可能會高得難以忍受;

4、到達速率很高,系統并發度很高,IO子系統延遲非常低,響應時間很快,例如使用的是SSD裝置。這種情況下,需求不容易出現積壓,不希望合并送出請求的情況經常發生,而更願意獲得對單一事務來講更低的延遲;

看來,commit_delay是針對後面兩種情況來調整的。對于高延遲的IO子系統,希望能夠盡量合并系統的送出請求來提升整體的吞吐量。一般來講IO子系統的延遲越高,commit_delay可以設定得越長。但前面也提到過,要防止設得過高,否則會矯枉過正,導緻系統吞吐量下降。對于低延遲的IO子系統,這個值可以設得低一些或者保留預設值。



   此外,PostgreSQL還有另外一個參數配合,稱為commit_siblings。這個參數用于控制commit_delay是否需要休眠。如果目前活動的事務少于commit_siblings,則commit_delay即算是非零值也不會進入休眠而且直接進行SYNC操作;反之則進入休眠狀态,等待其他事務的送出請求進來進行合并。這也是一個偵測到達速率的機制,如果到達速率不高,屬于前面的第1、2種情況,也就沒有必要休眠等待了。對于慢速IO裝置,我們希望合并的門檻低一些,盡可能地通過合并請求來提升吞吐量,是以commit_siblings可以設定得低一些;而對于低延遲高速IO裝置,這個參數值可以設得高一些,使得合并沒有這麼容易發生。


           

附官方文檔的一些建議:

1、在一些平台上,休眠最高的精度是10ms,是以在這些平台上,commit_delay設定1到10000的效果都是一樣的;

2、在某些平台也可能導緻休眠的時間稍長于commit_delay設定值;

3、如果需要設定commit_delay,建議以寫入一個8k資料塊平均時間的一半做為commit_delay的開始點;