小小 Postgres,何以替代 Redis、MongoDB 甚至 ES?

大家好,我是MAI麦造

最近又把之前做到一半的一个小网站维护了起来

之前停下的原因是因为这本来只是一个很小的功能,

但我需要分别写前后端

然后用 redis 做缓存、mongo 做存储、mysql 做后端存储、Elasticsearch 做全文索引的时候...

我是有点蚌埠住了

不过最近我找到了一个优雅的解决方案:postgres!!!

本文部分内容翻译自:Postgres is Too Good (And Why That's Actually a Problem)。 结尾点击阅读原文跳转。

Postgres 能搞定所有这些事

在固有的认知中,一直认为 Postgres "只是一个关系型数据库"。

必须为消息队列、全文检索使用"专业的工具"

但如果你知道:

  • Instagram 在单个 Postgres 实例上扩展到 1400 万用户

  • Discord 处理着数十亿的消息

  • Notion 整个产品都是基于 Postgres 构建的。

这个点的关键在于:他们不再像 2005 年那样使用 Postgres 了。

"专业工具"的隐藏成本

一个典型的"现代"技术栈成本如下:

  • Redis:每月 20 美元

  • 消息队列(Kafka/RebbitMQ):每月 25 美元

  • 搜索服务(Elasticsearch):每月 50 美元

  • 监控 3 个服务:每月 30 美元

  • 总计:$125/月

但这只是托管费用, 真正痛苦是,

维护成本:

  • 三个不同的服务用于监控、更新和调试

  • 不同的扩展模式和故障模式

  • 同时更新多种配置

  • 分离备份和灾难恢复流程

  • 每个服务都有不同的安全考虑因素

开发复杂性:

  • 不同的客户端库和连接模式

  • 处理多个服务之间的部署

  • 系统之间数据不一致

  • 复杂的测试场景

  • 不同的性能调优方法

如果选择自行托管,还需加上服务器管理、安全补丁,以及当 Redis 爆内存时,凌晨 3 点的维护...

而现在,你可以通过管理Postgres服务来处理所有这些!

这听起来有点疯狂,但接下来我将告诉你具体怎么实现:

队列系统

停止额外为 Redis 和 RabbitMQ 的云服务付费。

Postgres 原生支持 LISTEN / NOTIFY ,并且处理任务队列比大多数专用解决方案更出色:

python 复制代码
-- 简单的队列示例

CREATE TABLE job_queue (

id SERIAL PRIMARY KEY,

job_type VARCHAR(50),

payload JSONB,

status VARCHAR(20) DEFAULT 'pending',

created_at TIMESTAMP DEFAULT NOW(),

processed_at TIMESTAMP

);

-- ACID 任务处理

BEGIN;

UPDATE job_queue

SET status = 'processing', processed_at = NOW()

WHERE id = (

SELECT id FROM job_queue

WHERE status = 'pending'

ORDER BY created_at

FOR UPDATE SKIP LOCKED

LIMIT 1

)

RETURNING *;

COMMIT;

这个符合 ACID 标准的任务状态更新功能,

要是用 Redis 去搞,看看要掉多少头发?😏

我用这个方法处理反馈提交、发通知、更新路线图,

一个事务搞定,保证数据一致,不用操心消息代理那些破事儿。

Key-Value 键值存储

Redis 在大多数平台上最低也要 $20/月。

Postgres JSONB 直接用你现有的数据库就行,基本上你需要的功能它都涵盖了:

复制代码
-- Your Redis alternative

CREATE TABLE kv_store (

key VARCHAR(255) PRIMARY KEY,

value JSONB,

expires_at TIMESTAMP

);

-- GIN index for blazing fast JSON queries

CREATE INDEX idx_kv_value ON kv_store USING GIN (value);

-- Query nested JSON faster than most NoSQL databases

SELECT * FROM kv_store

WHERE value @> '{"user_id": 12345}';

这个 @> 操作符是 Postgres 的秘密武器!

比大多数 NoSQL 查询都快,而且数据也稳。

全文搜索

受不了 Elasticsearch 集群的又贵又复杂,那一定要试试Postgres 自带的全文搜索:

sql 复制代码
-- Add search to any table

ALTER TABLE posts ADD COLUMN search_vector tsvector;

-- Auto-update search index

CREATE OR REPLACE FUNCTION update_search_vector()

RETURNS trigger AS $$

BEGIN

NEW.search_vector := to_tsvector('english',

COALESCE(NEW.title, '') || ' ' ||

COALESCE(NEW.content, '')

);

RETURN NEW;

END;

$$ LANGUAGE plpgsql;

-- Ranked search results

SELECT title, ts_rank(search_vector, query) as rank

FROM posts, to_tsquery('startup & postgres') query

WHERE search_vector @@ query

ORDER BY rank DESC;

直接就能搞定模糊匹配词干提取相关性排序,简直不要太方便。

对于搜索,用户能瞬间在标题、描述和评论里找到所需。

根本不用 Elasticsearch 集群,纯粹靠 Postgres 就能发挥它最拿手的功能。

实时功能

还有那些复杂的 WebSocket 基础设施,也可以抛一边。

Postgres LISTEN / NOTIFY 直接给你实时更新,零额外服务:

sql 复制代码
-- Notify clients of changes

CREATE OR REPLACE FUNCTION notify_changes()

RETURNS trigger AS $$

BEGIN

PERFORM pg_notify('table_changes',

json_build_object(

'table', TG_TABLE_NAME,

'action', TG_OP,

'data', row_to_json(NEW)

)::text

);

RETURN NEW;

END;

$$ LANGUAGE plpgsql;

你的用程序监听这些通知,然后向用户推送更新。

完全不需要 Redis 的 pub/sub

ACID 事务

让我震撼的是:Postgres 强到能同时当你的主数据库、缓存、队列、搜索引擎,还搞实时系统。

最牛的是,啥都能保持 ACID 事务!

sql 复制代码
-- 一个事务,多个操作

BEGIN;

INSERT INTO users (email) VALUES ('user@example.com');

INSERT INTO job_queue (job_type, payload)

VALUES ('send_welcome_email', '{"user_id": 123}');

UPDATE kv_store SET value = '{"last_signup": "2024-01-15"}'

WHERE key = 'stats';

COMMIT;

要在 Redis、RabbitMQ 和 Elasticsearch 上搞这些操作,不哭都难。

可扩容的单个数据库

大部分人都不知道:单个 Postgres 实例真能扛住大场面。我指的是每天几百万笔交易,TB 级别的数据量,还有成千上万并发连接。

真实的案例

  • Airbnb:单个 Postgres 集群搞定上百万次预订

  • Robinhood:处理了数十亿笔金融交易

  • GitLab:整个 DevOps 平台都基于 Postgres

而真正厉害的地方是Postgres的架构。

它的垂直拓展做的很棒,但当你需要水平拓展的时候,也有这样成熟的方案可选:

  • Read replicas 只读副本 用来拓展查询

  • Partitioning 大表分区

  • 并发连接池

  • 分布式环境下的逻辑复制

大多数企业根本达不到这些限制。

你可以一直用单个实例,直到你要处理上百万用户或者复杂的分析工作负载,再考虑拓展架构。

从一开始就别瞎折腾了

现在开发里最大的坑就是搞那些花里胡哨的架构。

设计的系统,

要么是为了解决根本没出现过的难题,

要么是按着从未见过的流量去设计,

要么是想着可能永远也达不到的规模。

过度设计的死亡循环:

  1. "咱们总有一天得扩规模呢!"

  2. "快加上 Redis、队列、微服务、多个数据库试试!"

  3. 花几个月时间调试集成问题

  4. 上线后只有 47 个用户

  5. 凉凉...

每月花 200 美元买的基础设施,其实 5 美元的 VPS 就能搞定!

更好的方法是:

  • 用 Postgres 从简单开始试试!

  • 盯着真瓶颈,别瞎折腾那些假的!

  • 碰到真·瓶颈了,就针对性地给某些部件加码!

  • 只在你真的需要解决实际问题的时候才增加复杂性

要知道,你的用户根本不在乎你的架构。

他们关心的是你的产品能不能用,能不能解决他们的问题。

"我"的真实使用体验

我整个后端就一个 Postgres 数据库。

没 Redis,没 Elasticsearch,没消息队列。

就靠 Postgres 从用户认证到实时 WebSocket 通知全搞定!

它给我的系统提供了:

  • 实时更新用户提交的反馈

  • 数千个功能中的全文搜索

  • 后台任务用于发送通知

  • 缓存经常访问的路线图

  • 用键值对存储用户偏好和设置

结果呢?我发布新功能更快了,调试的环节也少了,基础设施成本几乎可以忽略不计。用户提交反馈、搜索功能或者获取路线图更新的实时信息------背后全都是 Postgres 在默默支撑着

这不是空谈了,是实际生产环境中的真实用户和真实数据。

什么时候 Postgres 不够用了?

当然,这不是说那些工具没用!

但当你真的需要的时候,这时你的系统可能是:

  • 每分钟处理超过 10 万个任务啊!

  • 得要亚毫秒级别的缓存响应速度

  • 你正在对 TB 级别的海量数据做复杂分析

  • 你们同时有成千上万用户呢!

  • 你这得全球数据分布还得有特定一致性要求啊

相关推荐
Elasticsearch4 小时前
Elasticsearch Python DSL 客户端开发
elasticsearch
麻辣布丁4 小时前
Git冲突原因与解决方法全解
大数据·git·elasticsearch
redreamSo6 小时前
想给产品加一个 AI 搜索,是上向量数据库还是用 MongoDB 就够了?
数据库·人工智能·mongodb
顧棟7 小时前
【ES实战】 低版本Elasticsearch(不具备CCR)集群迁移
大数据·elasticsearch·搜索引擎
莫得感情 o8 小时前
Redis 09 · 高可用:Sentinel 如何发现故障并完成切主
redis·缓存·sentinel
行业研究员8 小时前
腾讯云数据库 PostgreSQL 让相关子查询跑上多核
数据库·postgresql·腾讯云
Elastic 中国社区官方博客9 小时前
隐藏在可观测性数据中的安全攻击
大数据·网络·安全·elasticsearch·搜索引擎·全文检索
考虑考虑9 小时前
Redis8.8新特性
运维·redis·后端
tryxr11 小时前
Redis 的背景知识
数据库·redis·缓存
海兰11 小时前
Elasticsearch ES|QL:让全文本搜索无处不在
大数据·elasticsearch·jenkins