使用 Redis 缓存 PostgreSQL 查询的第一步
Redis 能瞬间解决你应用的所有性能问题吗?是的。
当然,事实并非如此。引入 Redis 来缓存数据库层确实可以提升性能。但需要注意的是,就像我们在开发过程中所做的所有事情一样,成功的一半在于制定策略。
计算机科学领域有个老笑话,说有两个难题:缓存失效和命名。和许多老笑话一样,这话也并非全无道理。缓存确实有可能解决性能瓶颈,并进一步提升现有 Postgres 实例的性能。但是,你需要先掌握一些基本知识。
在深入细节之前,让我们快速回顾一下 PostgreSQL 和 Redis。
PostgreSQL:真相
如果你使用的是 Rails、Laravel 或其他带有自身 ORM 的 Web 开发框架,很容易忘记数据背后的引擎。
首先要明确一点:PostgreSQL 速度很快,但它的首要任务是确保数据的准确性。PostgreSQL 是你的应用程序无可争议的真理来源。某些 NoSQL 数据库为了节省时间,会提供过时的记录版本,而 PostgreSQL 始终只提供最新数据。
Postgres 速度变慢的原因在于它强大的功能被滥用。“强大”这个词在技术领域常常被滥用,但用在 PostgreSQL 上却恰如其分。Postgres 几乎可以让你以无限种方式构建和查询数据。它赋予你对数据的强大掌控力,但这种掌控力也带来了无数种可能让你栽跟头的方法。
两大陷阱在于数据建模和查询设计。Web 框架 ORM 会尽力优化这两方面,但它们也必须具备通用性。一旦你注意到 Postgres 实例的速度,可能就意味着通用 ORM 已经达到了处理应用程序数据需求的极限。或者,你可能已经在使用手写查询,但它们的性能远未达到预期。
无论如何,引入缓存可以帮助你抵消低效数据模型和查询带来的问题,但是,除非你解决这些问题,否则你的数据库只会降低应用程序的整体效率。
Redis:加速器
如果说 PostgreSQL 代表真理,那么 Redis 代表速度。你可能已经知道 Redis 是一个内存键值存储系统。或许你曾用它来存储会话数据和类似的临时数据。由于 Redis 主要运行在内存中,因此它非常适合那些访问速度至关重要的数据类型。所以,它非常适合缓存,对吧?
是的——Redis的功能远不止这些。它不仅提供了多种不同的数据类型,而且还能将数据持久化到磁盘。
所以,Redis 也是真理吗?如果你愿意,它就可以是。而这正是为什么使用 Redis 缓存 PostgreSQL 会引发比你想象中更广泛的讨论。
将 Redis 与 PostgreSQL 结合使用的三种方法
因此,我们可以使用三种不同的方法来使用 Redis:
- 直读:通过在 Redis 中缓存常用数据,实现从 Postgres 的偏移读取。
- 回写:先将数据写入 Redis,然后再将其推送到 Postgres。
- 完全摒弃 Postgres:有些数据根本不需要放在 Postgres 中,而可以只存在于 Redis 中。
你怎么知道哪个是对的,什么时候是对的?
选择要缓存的内容
虽然没有硬性规定哪些内容应该缓存、哪些内容不应该缓存,但以下问题可以帮助您做出决定:
- 这个查询会影响用户体验吗?例如,如果某个查询阻塞了用户界面的渲染,那么它很可能适合缓存。
- 数据稍微过时有关系吗?有些数据必须保持最新,例如银行余额。而其他数据即使有些年头也不会产生任何负面影响。如果数据可以稍微过时,那么它就非常适合缓存。
- 随着使用量的增加,这个查询的执行次数也会增加吗?随着应用的发展,是否会有一些查询的执行次数越来越多?
- 我需要对这些数据运行复杂的查询吗?还是只需要以相同的方式从数据库中提取出来?如果你没有使用 PostgreSQL 的查询功能,那么也许就不需要把数据存储在数据库里。
- 我能承受数据丢失吗?即使你使用 Redis 的持久化功能,它仍然是内存优先的。因此,如果有些数据丢失是可以接受的,那么最好先将其写入 Redis,然后再根据需要将其写入 Postgres。
- 是否有更合适的专用工具?例如,日志。日志具有很高的写入吞吐量,而这并非 PostgreSQL 的强项,因此有一些专门的日志工具可以更好地完成这项工作。
而且,别忘了在做所有这些之前,你应该问自己一个问题:“我能否重写查询语句,使其在 PostgreSQL 上运行得更好?” 这并非故事的全部,但你应该先解决根本问题,而不是指望缓存能解决问题。
保持缓存最新
那个关于缓存失效的老笑话非常贴切,因为一旦你开始使用缓存,你就会花很多时间思考如何确保缓存中的数据是最新的。
何时刷新缓存取决于您希望在更新缓存的成本与提供过时数据的风险之间做出权衡。
有很多缓存失效策略可供选择,但总的来说,您会使用类似以下几种策略之一:
- 生存时间:您要求 Redis 在设定的时间段后自动使项目过期,这意味着您的数据层将不得不访问 PostgreSQL 来刷新项目。
- 写入时缓存:对于读取频率高且更改频率低的数据,每次写入 PostgreSQL 时都可以简单地更新缓存;但随着写入频率的增加,这种方法的成本会越来越高。
- 最近最少使用:这种驱逐方法侧重于释放资源,而不是保持数据新鲜,方法是从缓存中删除未被读取的数据。
以上三点只是简化版,但可以大致了解如何保持缓存新鲜。
迈出第一步
Redis 入门非常简单。你可以在笔记本电脑上进行尝试,而且 Rails、Laravel、Django 和大多数主流 Web 框架都有相应的软件包,可以帮助你快速上手。准备好投入生产环境后,像Heroku Redis这样的托管解决方案可以提供低运维的方式,让你无需承担维护服务器的额外开销即可将 Redis 部署到生产环境中。
一旦你体验过缓存,就会发现 Redis 的功能远不止于此。无论是 Redis 对发布/订阅消息的支持、使用 Lua 脚本进行高级查询,还是创建集群以实现高可用性,Redis 都可以在你的应用程序数据层中占据一席之地。
文章来源:https://dev.to/heroku/first-steps-to-caching-postgresql-queries-with-redis-2m71