狠狠色丁香婷婷综合尤物/久久精品综合一区二区三区/中国有色金属学报/国产日韩欧美在线观看 - 国产一区二区三区四区五区tv

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

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

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

導讀

近期,一篇名為“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是一個真正的數據庫,只是因為它速度非??欤梢栽谝幻腌妰葓绦袛蛋偃f次操作,被大家常用來作為緩存。


而當我看到最喜歡的關系型數據庫 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