天天看點

PostgreSQL 同步流複制鎖瓶頸分析

digoal

2016-11-07

postgresql , 同步流複制 , mutex , linux , latch

postgresql的同步流複制實際上是通過walsender接收到的walreceiver的lsn位點,來喚醒和釋放那些需要等待wal已被備庫接收的事務的。

對同步事務來說,使用者發起結束事務的請求後,産生的record lsn必須要小于或等于walsender接收到的walreceiver回報的lsn位點。

這個是通過wait隊列來實作的,釋放隊列中的事務這個動作是由walsender完成的。

在使用postgresql的同步流複制時,使用insert的benchmark壓測,發現主節點的cpu資源,網絡,塊裝置都比較空閑,但是寫性能會被局限在一個範圍内無法提升。

同時在主節點發現有大量的mutex,堵塞了整個寫的性能。

使用單機多執行個體(即一台主機部署多個主庫,這種方式能消除執行個體級别的鎖,例如執行個體級别的wal相關的lock),但是無法消除這個mutex的影響。

1. postgresql.conf

2. 啟動

3. 2個備庫

4. 狀态檢視

1. 測試過程中觀察top輸出,還很空閑

2. 測試過程中觀察perf top輸出,可以看到kernel的占比很高,都是lock相關。

3. 測試結束後,檢視對應程序的gmon輸出,分析原因

3.1 sync節點對應的walsender程序gprof輸出

頭部花費很多。

分析消耗

syncrepwakequeue排名第7,它其中大量的開銷是排名第八的setlatch(self time也是最多的)

需要優化的話就是它了。

3.2 potential節點對應的walsender程序gprof輸出,因為這個walsender程序不負責releasewaiters,是以沒有這項開銷。

1. setlatch

2. syncrepwakequeue

3. syncrepreleasewaiters

latch_sigusr1_handler與sendselfpipebyte,喚醒信号

使用cgroup cpuset子系統,将cpu核數限定到15個左右,性能從7.6萬提升到了10萬tps

15個核應該是我這個測試case,mutex鎖以及其他的資料庫開銷達到的一個均衡狀态,性能最佳。當核數再增加時,性能反而下降,可能是多個cpu核之間的mutex鎖開銷放大的原因。

<a href="https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/resource_management_guide/sec-cpuset.html">https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/resource_management_guide/sec-cpuset.html</a>

多線程unblock thread( pthread_cond_broadcast )可能更加高效。

<a href="https://docs.oracle.com/cd/e19455-01/806-5257/sync-40617/index.html">https://docs.oracle.com/cd/e19455-01/806-5257/sync-40617/index.html</a>

<a href="http://pubs.opengroup.org/onlinepubs/9699919799/nframe.html">http://pubs.opengroup.org/onlinepubs/9699919799/nframe.html</a>

一主2備,要求至少一個副本落盤。

記錄每組測試的perf,profile,cpu,io,mem,net

sysbench , insert only

1. 單機單執行個體,副本在異機

測試4組 sync=off,local,remote_write,on

測試小結

remote_write,on時, 約7萬qps。

使用cgroup 将cpu限制在10個核時,另外将sync standby節點對應的wal sender程序放到1核的cpuset,可以提升到10萬 qps。

off, local 時,約30萬,22萬。

瓶頸在文章前面有分析,主要是同步互斥鎖。

2. 單機單執行個體,使用批量事務,排除網絡問題,突出commit等待的問題。

放開cgroup限制,塞10條insert在事務中, 可以達到2.2萬tps, 約22w qps (insert)。

也就是說commit 時,backend process會進入sleep狀态,等待wal sender來釋放它,commit越多,睡眠次數就越多,可能造成本文前面提到的瓶頸。

3. 單機多執行個體,副本在異機

單機部署4個master節點,每個master的2個standby分别在另外兩台實體機。

同時測試4個master的insert case, 總qps ~= 7w/s。

相比單節點沒有任何提升。

4. 單機多執行個體,副本在本地。使用unix socket連接配接。

本地多副本,排除網絡問題(排除cpu,io問題)

把一主兩備全部放到一台主機,確定網絡沒有瓶頸,replication使用unix socket連接配接,pgbench也使用unix socket連接配接。

由于本地的cpu,io都不是瓶頸,是以考慮把同步的 standby放到本機,另外一個potention的standby放到異機。

測試結果依舊總qps ~= 7w/s。

沒有任何提升,同時機器的cpu,io都很空閑。

5. 單機,建立多個虛拟機隔離系統級别同步互斥鎖的問題。副本在異機。

在master的主機上,安裝8個kvm虛拟機,每個虛拟機安裝一個postgresql master執行個體。

standby部署在另外兩台實體機。

壓測有了性能提升,合并後的qps 19萬。

考慮到kvm的cpu指令翻譯,virtio有一定的性能損耗,同時還有網絡延遲的消耗,是以沒有達到理論值22萬。

但是這個結果也說明了一個問題,使用kvm後,規避了os層面的同步互斥鎖。

7. 單機測試,無副本

sync=off, on

約30萬,22萬。

繼續閱讀