在PostgreSQL中,複製延遲發生在主伺服器上的變更需要時間才能在副本伺服器上反映出來。無論您使用的是串流複製還是邏輯複製,延遲都可能影響性能、一致性和系統可用性。這篇文章涵蓋了複製類型、它們的差異、延遲原因、估算延遲的數學公式、監控技術以及減少複製延遲的策略。
PostgreSQL中的複製類型
串流複製
串流複製持續地將預寫日誌(WAL)變更從主伺服器即時傳送到一個或多個副本伺服器。副本會按收到的順序應用變更。這種方法會複製整個數據庫,並確保副本保持同步。
優點
- 低延遲,幾乎即時同步。
- 適用於完整數據庫複製。
缺點
- 副本為只讀,因此所有寫入交易必須發送到主節點。
- 如果網路連接中斷,延遲可能會顯著增加。
邏輯複製
邏輯複寫傳輸的是數據級別的更改,而不是低級別的WAL數據。它支持選擇性複寫,只複寫特定表或數據庫的部分。邏輯複寫使用邏輯解碼過程將WAL更改轉換為類似SQL的更改。
優點
- 允許選擇性地複寫特定表或模式。
- 支持具有衝突解決選項的可寫副本。
缺點
- 由於邏輯解碼開銷,導致較高的延遲。
- 對於大型數據集,效率低於流式複寫。
複寫延遲的原因
當主服務器上更改生成的速率超過可以處理和應用到副本服務器的速率時,就會出現複寫延遲。這種不平衡可能是由於各種潛在因素引起的,每個因素都會導致數據同步延遲。複寫延遲最常見的原因包括:
網絡延遲
網絡延遲是指數據從主服務器傳輸到副本服務器的時間。在流式複寫期間,WAL(預寫式日誌)段持續通過網絡傳輸。即使是網絡傳輸的輕微延遲也可能累積,導致副本延遲。
原因
- 高網絡往返時間(RTT)。
- 需要更多帶寬來處理大量的WAL數據。
- 網絡擁塞或封包丟失。
如果主要伺服器在高峰時段生成了大量變更,緩慢或過載的網絡可能會導致瓶頸,阻止複本接收 WAL 變更。
解決方案
使用低延遲、高帶寬的網絡連接,並啟用 WAL 壓縮 (wal_compression = on
) 以減少傳輸過程中的數據大小。
I/O 瓶頸
I/O 瓶頸發生在複本伺服器的磁盤寫入速度太慢,無法寫入來自 WAL 的變更。流式複製依賴於在應用之前將變更寫入磁盤,因此 I/O 子系統中的任何延遲都可能導致滯後。
原因
- 硬碟速度慢或過載 (HDD)。
- 磁盤寫入吞吐量不足。
- 來自其他進程的磁盤爭用。
- 如果複本伺服器使用旋轉式硬碟 (HDD) 而非固態硬碟 (SSD),則 WAL 變更可能無法快速寫入以跟上數據變更速度,從而導致複本落後主要伺服器。
解決方案
為優化複本的磁盤 I/O,使用 SSD 以提高寫入速度,並將複製過程與其他磁盤密集型任務隔離。
CPU/內存限制
複製過程需要 CPU 和記憶體來解碼、寫入和應用更改。如果複本伺服器缺乏足夠的處理能力或記憶體,可能會難以跟上輸入修改,導致複製延遲。
原因
- 有限的 CPU 核心或慢處理器。
- WAL 緩衝區的記憶體不足。
- 其他進程佔用 CPU 或記憶體資源。
- 如果複本正在處理大型交易或在複製過程中運行查詢,CPU 可能會飽和,從而減慢複製過程。
解決方案
為複本伺服器分配更多 CPU 核心和記憶體。增加 wal_buffers 的大小以提高 WAL 處理效率。
主伺服器上的重負載
當主伺服器產生變更速度過快,複本無法處理時,也可能出現複製延遲。大型交易、批量插入或頻繁更新可能會壓倒複製。
原因
- 批量數據導入或大型交易。
- 對大型表的高頻更新。
- 主伺服器上的高並發工作負載。
- 如果主伺服器同時處理多個大型交易,例如在批量數據導入期間,事務負載可能過重。WAL 數據的數量可能超過複本實時處理的範圍,增加延遲。
解決方案
通過批量處理較小的更新並避免長時間運行的交易來優化交易。如果嚴格的同步不是關鍵,則使用異步複製來減少複製負擔。
資源競爭
當多個進程競爭相同的資源,如 CPU、內存或磁碟 I/O 時,就會發生資源競爭。這可能發生在主伺服器或副本伺服器上,並導致複製處理的延遲。
原因
- 其他進程消耗磁碟 I/O、CPU 或內存。
- 備份或分析等背景任務同時運行。
- 複製流量與其他數據傳輸之間的網絡競爭。
- 如果副本伺服器還在運行備份或分析查詢,則 CPU 和磁碟資源的競爭可能會減慢複製過程。
解決方案
將複製工作負載與其他資源密集型進程隔離。在非高峰時段安排備份和分析,以防止對複製的干擾。
複製延遲的數學公式
使用以下公式計算複製延遲:
在邏輯複製中,邏輯解碼會消耗額外的時間:
監控複製延遲
流式複製監控
pg_stat_replication 檢視可用於監控流式複寫延遲。它提供了主要和副本伺服器之間的狀態和延遲洞察。
SELECT application_name, state,
pg_size_pretty(sent_lsn - write_lsn) AS lag_bytes,
sync_state
FROM pg_stat_replication;
sent_lsn
: 最後一個發送到副本的WAL位置。write_lsn
: 在副本上寫入的最後一個WAL位置。lag_bytes
: 兩者之間的差異表示延遲。
邏輯複寫監控
邏輯複寫 延遲可以使用 pg_stat_subscription 檢視來監控。
SELECT subscription_name, active,
pg_size_pretty(pg_current_wal_lsn() - replay_lsn) AS lag_bytes
FROM pg_stat_subscription;
範例: 視覺化複寫延遲
以下Python程式碼片段可視化隨時間變化的流式和邏輯複寫延遲。
import matplotlib.pyplot as plt
time = ['12:00', '12:10', '12:20', '12:30', '12:40', '12:50', '13:00']
streaming_lag = [0.5, 0.6, 0.4, 0.7, 1.0, 0.9, 0.6]
logical_lag = [2.0, 2.5, 3.0, 2.8, 3.5, 4.0, 3.2]
plt.plot(time, streaming_lag, label='Streaming Replication Lag', marker='o')
plt.plot(time, logical_lag, label='Logical Replication Lag', marker='s')
plt.xlabel('Time')
plt.ylabel('Lag (seconds)')
plt.title('Replication Lag Over Time')
plt.legend()
plt.grid(True)
# Save the plot as an image file
plt.savefig('replication_lag_plot.png')
print("Plot saved as replication_lag_plot.png")
生成的圖表比較了流式和邏輯複寫的效能。由於解碼和處理開銷,邏輯複寫的延遲往往更加變化。
如何減少複寫延遲
1. 優化WAL配置
- 增加
wal_buffers
以在記憶體中保存更多WAL資料。 - 將
wal_writer_delay
設定為較低值(例如10毫秒),以更快寫入WAL資料。
wal_buffers = 64MB
wal_writer_delay = 10ms
2. 改善網路效能
- 在主要和副本之間使用低延遲、高頻寬的網路連線。
- 在傳輸過程中壓縮WAL資料以減少傳輸時間:
wal_compression = on
。
3. 在可能的情況下使用非同步複寫
-
非同步複寫通過不等待副本確認更改來減少延遲,但會增加數據丟失風險。
ALTER SYSTEM SET synchronous_commit = 'off';
4. 在邏輯複寫中啟用平行應用
-
PostgreSQL 14+ 允許邏輯變更的平行應用,減少大型交易的延遲。
ALTER SUBSCRIPTION my_subscription SET (parallel_apply = on);
5. 為副本分配更多資源
- 確保複本具有足夠的CPU和內存以快速處理WAL更改。
- 在複本上使用SSD以加快磁盤I/O。
6. 批處理交易
-
將多個較小的更新合併為更少的交易以減少開銷。
現實世界的例子
減少流式複製延遲
某家運行高流量PostgreSQL集群的公司在高峰時段面臨複製延遲的問題。通過將wal_buffers
增加到64MB並將wal_writer_delay
減少到10ms,將複製延遲減半。切換到高速網絡連接將延遲降低到不到一秒。
減少邏輯複製延遲
具有多個邏輯訂閱的系統在高寫入工作負載期間遇到延遲。在PostgreSQL 14中啟用並行應用程序將工作負載分散到眾多工作程序,將複製延遲從4秒降低到不到1秒。
結論
複製延遲是影響PostgreSQL系統性能和一致性的關鍵問題。流式複製提供低延遲,但需要複製整個數據庫,而邏輯複製提供靈活性但開銷較高。通過使用pg_stat_replication
和pg_stat_subscription
進行定期監控,管理員可以檢測和減輕延遲。
優化WAL配置、改善網絡性能、使用並行應用程序並分配足夠的資源可以顯著減少延遲。適當的調整確保副本保持同步,系統保持高可用性和性能。
Source:
https://dzone.com/articles/understanding-and-reducing-postgresql-replication-lag