Posted in

Postgres 可以替代 Redis 作为缓存吗?_AI阅读总结 — 包阅AI

包阅导读总结

1. `Postgres`、`Redis`、`缓存`、`WAL`、`逐出策略`

2. 本文探讨了能否用 Postgres 替代 Redis 作为缓存,提到通过 UNLOGGED 表将其转变为缓存服务,比较了 Postgres 和 Redis 在数据持久化机制上的差异,还讨论了过期和逐出策略的实现及相关问题。

3.

– Postgres 作为缓存

– 通过 UNLOGGED 表实现,此表不生成 WAL

– WAL 确保数据更改记录,系统崩溃时维护数据完整性

– Redis 有类似机制 AOF

– 过期策略

– 可用存储过程实现,如 expire_rows

– 存在复杂性,多数应用不依赖,管理麻烦,需按计划调用

– 可使用扩展 pg_cron 进行调度

– 逐出策略

– 可添加 last_read_timestamp 列实现 LRU 策略

– Redis 提供八种现成逐出策略,Postgres 可问 ChatGPT 设定其他策略

思维导图:

文章地址:https://mp.weixin.qq.com/s/i1_HUkcoCcXDdZT7xvdr0w

文章来源:mp.weixin.qq.com

作者:Raphael

发布时间:2024/7/21 18:24

语言:中文

总字数:4308字

预计阅读时间:18分钟

评分:82分

标签:数据库,缓存,Postgres,Redis,性能优化


以下为原文内容

本内容来源于用户推荐转载,旨在分享知识与观点,如有侵权请联系删除 联系邮箱 media@ilingban.com

Stephan 和 Martin 都表示,我们可以通过使用 UNLOGGED 表将 Postgres 变成缓存服务。
结合Martin Heinz《你不需要专用的缓存服务 – PostgreSQL 作为缓存这篇文章内容(链接:https://martinheinz.dev/blog/105),得到了这些答案:
Postgres 中的未记录表是一种防止特定表生成 WAL(预写日志)的方法。
反言之,WAL可确保对数据库所做的所有更改,在实际写入数据库文件之前都已记录。在系统崩溃和断电等极端情况的时候,就有助于维护数据完整性。
补充说明:Redis提供了一种类似的机制,称为仅附加文件 (AOF) ,它不仅提供了一种在 Redis中持久保存数据的机制,而且还以类似的方式运行,即记录在 Redis 中执行的所有操作。如果使用 Redis 作为主数据库,我们会启用 AOF ,而如果使用 Postgres 作为缓存,我们会关闭(在特定表上)WAL。
对于每次数据修改,Postgres 必须更改写入 WAL 和数据文件。这使所需的写入操作数量加倍。
除此之外,为了确保每个已提交的事务都物理写入磁盘,WAL被设计为强制执行磁盘刷新 (fsync)。频繁的磁盘刷新操作会影响性能,因为它们会引入等待磁盘确认数据已安全写入的延迟。
Postgres会使用WAL来重放和应用自上次检查点以来所做的任何更改,如果我 们没有此日志记录,则无法通过重放WAL记录将数据库恢复到一致状态。但这也是缓存的一大特点。
CREATE UNLOGGED TABLE cache ( id serial PRIMARY KEY, key text UNIQUE NOT NULL, value jsonb,inserted_attimestamp);
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;
CALLexpire_rows('60minutes');
然而事实是,大多数现代应用程序不再依赖存储过程,而且现在很多软件开发人员都反对使用存储过程,以此避免把业务逻辑泄露到数据库中,且随着存储数据的增加,管理和理解会变得更为麻烦。
此外,我们还需要按计划调用这些存储过程。为此,我们需要使用一个扩展 pg_cron 。安装扩展后,我们仍然需要创建调度程序:
SELECT cron.schedule('0 * * * *', $$CALL expire_rows('1 hour');$$);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 lru_eviction(10);
Redis 提供了八种现成的逐出策略(官方文档:https://redis.io/docs/latest/develop/reference/eviction/)。如果想要为“Postgres Cache”设置另一种逐出策略?问ChatGPT即可。