欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發文檔 其他文檔  
 
網站管理員

Postgres 可以替代 Redis 作為緩存嗎?

admin
2024年7月22日 23:1 本文熱度 654

導讀

近期,一篇名為“Postgres 可以替代 Redis 作為緩存嗎?”的文章在Medium迅速出圈,這一新穎的話題,似乎能帶來不少實際項目的啟示,下面跟隨著作者Raphael De Lio來解讀這一疑問。

先說結論:不能替代,還差得遠。

我在Twitter上詢問大家了一個問題:你想到的第一個消息隊列是什么?


其中一個回答引起我的注意:Postgres

“使用 Postgres 作為消息隊列,并使用 SKIP LOCKED 代替 Kafka(如果你只需要一個消息隊列的話)”。— Stephan Schmid

更令我驚訝的是,還有提出使用Postgres作為緩存來替代 Redis的觀點。

“使用 Postgres 進行緩存,而不是 Redis。使用 UNLOGGED 表和 TEXT 作為 JSON 數據類型。存儲過程可以使用 ChatGPT 編寫,添加和強制執行數據的到期日期,就像在 Redis一樣”。— Stephan Schmidt


在我學習 Redis 的過程中,我經常聽到很多人(來自 Redis)提倡:Redis可以成為你的主要數據庫。

這可能是一個好主意。Redis是一個真正的數據庫,只是因為它速度非常快,可以在一秒鐘內執行數百萬次操作,被大家常用來作為緩存。


而當我看到最喜歡的關系型數據庫 Postgres 可以取代我最喜歡的非關系型數據庫 Redis 時,我的世界發生了翻天覆地的變化。我應該用Postgres取代 Redis,還是用Redis取代Postgres?

在考慮這個問題之前,我想先搞清楚:Postgres作為緩存真的是個好主意嗎?它真的可以取代 Redis 嗎?

Stephan Schmidt主張用 Postgres 替換 Redis(實際上他主張用 Postgres 替換一切),他認為這樣做可以消除一定的復雜性。(請閱讀:https://medium.com/@AmazingCTO)

“一切都用 Postgres 吧(如何降低復雜性并加快速度)” — Stephan Schmid

然而,他并不是唯一一個主張更換 Redis 的人,也有人做了同樣的事情:


但首先,我為什么要用 Postgres 替換 Redis?


Stephan 已經給出了兩個理由:復雜性更低和變化更快。是否還有其他驅動因素呢?

使用 Postgres 作為緩存雖不是常見的選擇,但在某些情況下具有一定的優勢:

統一技術棧     

Postgres 是最流行的數據庫之一,且開源免費,將其用作緩存可以減少管理和維護多個數據庫系統的工作,從而簡化技術堆棧。

熟悉的界面

Postgres 支持復雜的查詢和索引,特別是對于精通 SQL的人來說,直接在緩存層內處理高級數據檢索和轉換任務會更加容易。

成本

某些情況下,使用現有的 Postgres 資源進行緩存,可能比部署單獨的緩存解決方案(如 Redis)更具成本效益。尤其是在基礎設施預算有限的環境中,將 Postgres 同時用作主存儲和緩存可以提高資源利用率。


我們對緩存服務有怎樣的目標?


傳統緩存服務(例如 Redis)具有一系列可增強應用程序性能和可擴展性的功能,Postgres 是否真的可以取代 Redis,需要從以下幾個關鍵層面考量:

表現

緩存服務的主要目標,是通過加快數據訪問速度,來提高應用程序的性能。 

高性能緩存解決方案可以處理高吞吐量工作負載,并提供亞毫秒級的響應時間,從而顯著加快檢索數據的進程。

刪除策略

通過設置緩存數據的過期時間,讓過期數據在指定時間后自動從緩存中刪除。確保過期數據不會提供給應用程序。 

逐出策略

緩存服務通常將其數據保存在內存中,而內存一般是有限的。因此,需要設置逐出策略讓我們自動刪除不常用的數據,為新數據騰出空間。

鍵值存儲

大多數緩存服務的核心都是以鍵值對的形式存儲數據。這種簡單但功能強大的模型可以快速檢索數據,從而輕松高效地存儲和訪問常用數據。

簡而言之,緩存服務需要更快地訪問數據并返回盡可能最新的數據。


怎樣才能將 Postgres 變成緩存?


Stephan 和 Martin 都表示,我們可以通過使用 UNLOGGED 表將 Postgres 變成緩存服務。

結合Martin Heinz《你不需要專用的緩存服務 - PostgreSQL 作為緩存》這篇文章內容(鏈接:https://martinheinz.dev/blog/105),得到了這些答案:

未記錄表和預寫日志

Postgres 中的未記錄表是一種防止特定表生成 WAL(預寫日志)的方法。 

反言之,WAL可確保對數據庫所做的所有更改,在實際寫入數據庫文件之前都已記錄。在系統崩潰和斷電等極端情況的時候,就有助于維護數據完整性。

補充說明:Redis提供了一種類似的機制,稱為僅附加文件 (AOF) ,它不僅提供了一種在 Redis中持久保存數據的機制,而且還以類似的方式運行,即記錄在 Redis 中執行的所有操作。如果使用 Redis 作為主數據庫,我們會啟用 AOF ,而如果使用 Postgres 作為緩存,我們會關閉(在特定表上)WAL。

關閉WAL提高性能

對于每次數據修改,Postgres 必須更改寫入 WAL 和數據文件。這使所需的寫入操作數量加倍。

除此之外,為了確保每個已提交的事務都物理寫入磁盤,WAL被設計為強制執行磁盤刷新 (fsync)。頻繁的磁盤刷新操作會影響性能,因為它們會引入等待磁盤確認數據已安全寫入的延遲。

放棄堅持

未記錄表不是持久的。 

Postgres會使用WAL來重放和應用自上次檢查點以來所做的任何更改,如果我 們沒有此日志記錄,則無法通過重放WAL記錄將數據庫恢復到一致狀態。但這也是緩存的一大特點。

CREATE UNLOGGED TABLE cache (

    id serial PRIMARY KEY,

    key text UNIQUE NOT NULL,

    value jsonb,

    inserted_at timestamp);


CREATE INDEX idx_cache_key ON cache (key);


存儲過程的過期

Martin 和 Stephan 都表示,可以使用存儲過程來實現過期,這會導致一定的復雜性。

因此,Stephan甚至更進一步建議我們使用ChatGPT來編寫存儲過程。

CREATE OR REPLACE PROCEDURE expire_rows (retention_period INTERVAL) AS

$$

BEGIN

    DELETE FROM cache

    WHERE inserted_at < NOW() - retention_period;


    COMMIT;

END;

$$ LANGUAGE plpgsql;


CALL expire_rows('60 minutes'); -- This will remove rows older than 1 hour


然而事實是,大多數現代應用程序不再依賴存儲過程,而且現在很多軟件開發人員都反對使用存儲過程,以此避免把業務邏輯泄露到數據庫中,且隨著存儲數據的增加,管理和理解會變得更為麻煩。

此外,我們還需要按計劃調用這些存儲過程。為此,我們需要使用一個擴展 pg_cron 。安裝擴展后,我們仍然需要創建調度程序:

-- Create a schedule to run the procedure every hour

SELECT cron.schedule('0 * * * *', $$CALL expire_rows('1 hour');$$);

-- List all scheduled jobs

SELECT * FROM cron.job;


然而,復雜性還在持續增加。

存儲過程逐出策略

Stephan在他的文章中沒有提到逐出策略,而Martin則表示,由于過期可以保持存儲大小,因此也可以作為一個選擇。

但是,如果仍然想要啟用逐出策略,Martin建議在我們的表中添加一個名為 last_read_timestamp的列,并偶爾運行另一個存儲過程來實現“最近使用”(LRU)逐出策略。

CREATE OR REPLACE PROCEDURE lru_eviction(eviction_count INTEGER) AS

$$

BEGIN

    DELETE FROM cache

    WHERE ctid IN (

        SELECT ctid

        FROM cache

        ORDER BY last_read_timestamp ASC

        LIMIT eviction_count

    );


    COMMIT;

END;

$$ LANGUAGE plpgsql;

-- Call the procedure to evict a specified number of rows

CALL lru_eviction(10); -- This will remove the 10 least recently accessed rows


Redis 提供了八種現成的逐出策略(官方文檔:https://redis.io/docs/latest/develop/reference/eviction/)。如果想要為“Postgres Cache”設置另一種逐出策略?問ChatGPT即可。


性能表現如何?


性能表現是緩存服務選型的決定性因素,因為我們需要緩存服務的主要原因是想更快地訪問的數據。

Greg Sabino Mullane在他的文章《PostgreSQL Unlogged Tables — Look Ma, No WAL! 》中展示了測試結果(原文鏈接:https://www.crunchydata.com/blog/postgresl-unlogged-tables),比較了 Postgres 中 UNLOGGED 和 LOGGED 表的性能。數據顯示, 寫入 UNLOGGED 表的性能是在 LOGGED 表中執行相同操作的兩倍。具體數據如下:

  • 未記錄表
延遲:2.059 ms
TPS:485,706168

  • 記錄表
延遲:5.949 ms
TPS:168,087557

讀寫表現如何呢?

這就是最大的問題:Postsgres 性能優化策略依賴于共享緩沖區。

共享緩沖區將經常訪問的數據和索引直接存儲在內存中,使其可以快速訪問,并減少從磁盤讀取的需要,提高已記錄和未記錄表的查詢性能和數據訪問能力。

未記錄表可能留在這些緩沖區中,但如果它們變得太大或內存有限,它們則會被寫入磁盤。因此,未記錄表主要提高寫入速度,而不是讀取速度。

為了證明這一點,我使用進行了快速實驗 pgbench (具體操作請見:GitHub - raphaeldelio/redis-postgres-cache-benchmark)

結果表明,記錄表和未記錄表的性能實際上非常相似,讀取這兩種類型的表平均需要大約 0.650 ms。具體數據如下:

  • 未記錄表 
延遲:0.679 ms
TPS:14.724,204

  • 記錄表
延遲:0.627ms
TPS :15.946,025

這一結果測試進一步驗證:未記錄表主要增強了寫入性能。

對于讀取操作,未記錄表的性能優勢并不明顯,因為記錄表和未記錄表都同樣受益于 Postgres 的緩存和優化策略。

與 Redis 相比性能如何?

除了對 Postgres 進行基準測試之外,我還對 Redis 進行了實驗。(具體操作請見:GitHub - raphaeldelio/redis-postgres-cache-benchmark)。結果顯示,Redis在讀寫操作方面具有顯著的性能優勢: 

  • 讀取
延遲 (p50) :0.095ms
每秒請求數 (RPS) :892.857,12 

  • 寫入
延遲 (p50) :0.103ms
每秒請求數 (RPS) :892857,12 

性能比較顯示,Redis 在寫入和讀取操作方面都明顯優于 Postgres:Redis只有 0.095ms的延遲, Postgres未記錄表有0.679ms。

Redis還能處理更高的請求率,每秒 892,857.12 個請求,而 Postgres 每秒只能處理 15,946.025 個請求。 

在寫入操作方面,我們也可以看到Redis提供了更優異的性能,吞吐量明顯更高,延遲也更低。

如果我在 RAM 中運行 Postgres 會怎樣?

在審查本文的過程中,Xebia的同事Maksym Fedorov表示:

“ 如果現在在與內存映射文件對應的表空間中創建未記錄表會怎么樣?我猜我們會看到完全不同的數字。”

為了測試這一點,我使用保存在 RAM 中的 Postgres 數據運行了基準測試。 令人驚訝的是,結果沒有任何改善。基準測試顯示:

  • 讀取
延遲:0.652ms
每秒請求數 (TPS) :15329,776954

經過進一步研究,我了解到,即使數據存儲在 RAM 中,在Postgres 的共享緩沖區內訪問數據也會產生額外成本,這些成本來自管理鎖,以及數據完整性和并發訪問所需的其他內部進程。

而且,Postgres總是先檢查數據是否在共享緩沖區中,如果不在,它會先將數據從tmpfs文件系統復制到共享緩沖區中,然后再提供服務,即使數據庫保存在 RAM中。


我應該用 Postgres 替換 Redis 嗎?


綜上所述,如果您需要緩存服務來提高寫入性能,可以使用未記錄表優化 Postgres。但是,雖然未記錄表比記錄表提供更好的寫入性能,但與 Redis 相比仍然不足。

使用緩存服務的主要原因是縮短數據檢索時間。未記錄的表不會提高讀取性能,而Redis則以極快的讀取優勢作為更優選擇。

此外,Redis有助于防止大量低成本查詢訪問數據庫,這是未記錄表無法提供的優勢。Redis還提供內置功能,如過期、逐出策略等,這些功能在 Postgres 中很難實現。

盡管對某些人來說,管理 Postgres 似乎更容易,但將 Postgres 變成緩存并不能提供專用緩存服務的優勢。同時,Redis 的學習、部署和使用都很簡單,而且很有趣。

所以為了獲得更快的性能和簡單性,選擇像Redis這樣真正的緩存服務似乎才是更明智的選擇。


作者丨Raphael De Lio   編譯丨Rio

來源丨https://medium.com/redis-with-raphael-de-lio/can-postgres-replace-redis-as-a-cache-f6cba13386dc

該文章在 2024/7/23 20:47:56 編輯過
關鍵字查詢
相關文章
正在查詢...
點晴ERP是一款針對中小制造業的專業生產管理軟件系統,系統成熟度和易用性得到了國內大量中小企業的青睞。
點晴PMS碼頭管理系統主要針對港口碼頭集裝箱與散貨日常運作、調度、堆場、車隊、財務費用、相關報表等業務管理,結合碼頭的業務特點,圍繞調度、堆場作業而開發的。集技術的先進性、管理的有效性于一體,是物流碼頭及其他港口類企業的高效ERP管理信息系統。
點晴WMS倉儲管理系統提供了貨物產品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質期管理,貨位管理,庫位管理,生產管理,WMS管理系統,標簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費OA是一款軟件和通用服務都免費,不限功能、不限時間、不限用戶的免費OA協同辦公管理系統。
Copyright 2010-2025 ClickSun All Rights Reserved