文章的翻譯是專門為課程的學生準備的
PostgreSQL 和特定於連接的寫入一致性設置
在 Compose,我們處理許多資料庫,這使我們有機會更加熟悉它們的功能和缺點。 當我們逐漸喜歡新資料庫的功能時,我們有時會開始思考,如果我們長期使用的更成熟的工具中也存在類似的功能,那該有多好。 我希望在 PostgreSQL 中看到的新功能之一是整個叢集中每個連接的可配置寫入一致性。 事實證明,我們已經擁有它,今天我們想與您分享有關如何使用它的資訊。
為什麼我需要它?
叢集的行為方式取決於您的應用程式。 以帳單支付應用程式為例。 您將需要整個叢集 XNUMX% 的一致性,因此您必須啟用同步提交,以便資料庫等待所有變更的完成。 但是,如果您的應用程式是一個快速增長的社交網絡,那麼您可能更喜歡快速回應而不是 XNUMX% 一致性。 為此,您可以在叢集中使用非同步提交。
滿足妥協
您必須在資料一致性和效能之間進行權衡。 PostgreSQL 放棄了一致性,因為預設配置是可預測的並且不會出現意外的情況。 現在讓我們看看妥協的情況。
權衡 1:效能
如果PostgreSQL叢集不需要一致性,可以非同步運行。 寫入是對叢集領導者進行的,更新將在幾毫秒後發送到其副本。 當PostgreSQL叢集需要一致性時,它必須同步運作。 寫入將發送到叢集領導者,叢集領導者將向副本發送更新,並等待每個副本都已寫入的確認,然後向發起寫入成功的客戶端發送確認。 這些方法之間的實際差異在於,非同步方法需要兩個網路躍點,而同步方法需要四個網路躍點。
權衡 2:一致性
這兩種方法如果領導者失敗,結果也會不同。 如果工作是非同步執行的,那麼如果發生此類錯誤,副本將不會提交所有記錄。 會損失多少? 取決於應用程式本身和複製的效率。 如果副本中的資訊量比領導者少 1 MB,Compose 複製將阻止副本成為領導者,也就是說,在非同步操作期間可能會遺失多達 1 MB 的記錄。
在同步模式下不會發生這種情況。 如果領導者發生故障,所有副本都會更新,因為領導者上確認的任何寫入都必須在副本上確認。 這就是一致性。
同步行為在計費應用程式中很有意義,其中一致性在一致性和效能之間的權衡中具有明顯的優勢。 對於此類應用程式來說,最重要的是有效數據。 現在考慮一個社交網絡,其中的主要任務是透過盡快回應請求來保持用戶的注意力。 在這種情況下,具有更少網路躍點和更少等待提交的效能將是優先考慮的。 然而,效能和一致性之間的權衡並不是您必須考慮的唯一問題。
權衡 3:崩潰
了解集群在故障期間的行為非常重要。 考慮一個或多個副本發生故障的情況。 當非同步處理提交時,領導者將繼續運行,即接受並處理寫入,而無需等待遺失的副本。 當副本返回叢集時,它們會趕上領導者。 使用同步複製,如果副本沒有回應,那麼領導者將別無選擇,將繼續等待提交確認,直到副本返回叢集並可以接受並提交寫入。
每筆交易一個連結?
每個應用程式都需要不同類型的一致性和效能組合。 當然,除非它是我們想像中完全一致的帳單支付應用程序,或者是我們幾乎短暫的社交網路應用程式。 在所有其他情況下,有時某些操作必須同步,而某些操作必須非同步。 您可能不希望系統等到發送到聊天的訊息被提交,但如果在同一應用程式中處理付款,那麼您將不得不等待。
當然,所有這些決定都是由應用程式開發人員做出的。 就何時使用每種方法做出正確的決定將有助於您充分利用集群。 開發人員可以在 SQL 層級在連線和事務之間進行切換,這一點很重要。
確保實務中的控制
預設情況下,PostgreSQL 提供一致性。 這是由伺服器參數控制的 synchronous_commit
。 預設情況下它處於位置 on
,但它還有其他三個選項: local
, remote_write
或 off
.
當將參數設為 off
所有同步提交都會停止,即使在本機系統上也是如此。 local 參數指定本機系統的同步模式,但對副本的寫入是非同步執行的。 Remote_write
更進一步:對副本的寫入是非同步進行的,但當副本已接受寫入但尚未將其寫入磁碟時返回。
透過考慮可用的選項範圍,我們選擇一種行為,並記住 on
– 這些是同步錄音,我們將選擇 local
用於透過網路進行非同步提交,同時保持本地提交同步。
現在,我們稍後將告訴您如何進行設置,但想像一下我們設置 synchronous_commit
в local
對於伺服器。 我們想知道是否可以更改參數 synchronous_commit
事實證明,這不僅是可能的,甚至還有兩種方法可以做到這一點。 首先是設定連線的會話,如下所示:
SET SESSION synchronous_commit TO ON;
// Your writes go here
會話中的所有後續寫入將在連接的用戶端傳回肯定結果之前確認副本的寫入。 當然除非你改變設置 synchronous_commit
再次。 可以省略部分 SESSION
在命令中,因為它將採用預設值。
當您只想確保獲得單一事務的同步複製時,第二種方法很好。 在許多 NoSQL 產生資料庫中不存在事務的概念,但在 PostgreSQL 中存在。 在這種情況下,您啟動一項事務,然後設定 synchronous_commit
в on
在執行交易條目之前。 COMMIT
將使用任何參數值提交事務 synchronous_commit
,這是當時設定的,儘管最好預先設定該變數以確保其他開發人員了解寫入不是異步的。
BEGIN;
SET LOCAL synchronous_commit TO ON;
// Your writes go here
COMMIT;
現在,在資料庫向連線的用戶端傳回肯定回應之前,所有交易提交都將被確認為寫入副本。
設定 PostgreSQL
在此之前,我們設想了一個 PostgreSQL 系統 synchronous_commit
,安裝在 local
。 為了在伺服器端實現這一點,您需要設定兩個伺服器設定選項。 多一個參數 synchronous_standby_names
當 synchronous_commit
將在 on
。 它決定哪些副本有資格進行同步提交,我們將其設定為 *
,這意味著所有副本都參與其中。 這些值通常配置在
synchronous_commit = local
synchronous_standby_names='*'
透過設定參數 synchronous_commit
進入意義 local
,我們建立一個系統,其中本地磁碟保持同步,但網路副本提交預設是異步的。 當然,除非我們決定使這些提交同步,如上所示。
如果您一直在關注事態發展
再說幾句話...
就在一週前,我可能會告訴你,不可能對 PostgreSQL 進行如此精細的調整。 就在那時,Compose 平台團隊的成員 Kurt 堅稱有這樣的機會。 他平息了我的反對意見,並在 PostgreSQL 文件中找到了
此設定可以隨時變更。 任何事務的行為均由提交時有效的設定決定。 因此,某些事務同步提交而另一些事務非同步提交是可能且有用的。 例如,強制一個 multistatement
當參數預設值相反時,事務要異步提交,設定 SET LOCAL synchronous_commit TO OFF
在一筆交易中。
透過對設定檔的這個小修改,我們讓使用者可以控制其一致性和效能。
來源: www.habr.com