找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

2520

积分

0

好友

364

主题
发表于 昨天 03:10 | 查看: 7| 回复: 0

过去几个月,我一直被一个问题困扰。

一些独立开发者和创业公司创始人疯狂地拼凑技术栈,用 Redis 做缓存,RabbitMQ 做队列,Elasticsearch 做搜索,还有 MongoDB,为什么呢?

我也犯过同样的错误。当初开发 UserJot(我的反馈和路线图工具)时,我的第一反应是设计一个“规范”的架构,把所有功能都拆分成独立服务。后来我停下来问自己:如果直接用 PostgreSQL 来处理所有事情呢?

事实证明,大家一直对这个显而易见的问题避而不谈:

PostgreSQL 几乎可以做到这一切。

它的效果比你想象的还要好。

一、“PostgreSQL 无法扩展”的谬论正在让你损失金钱

你肯定听说过 PostgreSQL “只是个关系型数据库”,需要专门的工具来完成特定的任务。我以前也是这么想的,直到我发现 Instagram 仅用一个 PostgreSQL 实例就能支持 1400 万用户;Discord 可以处理数十亿条消息;Notion 整个产品都是基于 PostgreSQL 开发的。

但关键在于:他们使用 PostgreSQL 的方式已经和 2005 年不一样了。

二、排队系统

别再为 RedisRabbitMQ 付费了。PostgreSQL 原生支持 LISTEN/NOTIFY,而且比大多数专用解决方案更能处理消息队列:

-- Simple job queue in pure Postgres
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-compliant job processing
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;

这样就能实现精确一次处理,而且无需任何额外的基础设施。如果试着用 Redis 实现这一点,你会抓狂的。

在 UserJot 中,我正是使用这种模式来处理反馈提交、发送通知和更新路线图项目。只需一次事务,就能保证数据一致性,而且无需消息代理,也能降低复杂性。

三、键值存储

Redis 在大多数平台上最低每月收费 20 美元。PostgreSQL 的 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}';

@> 操作符是 PostgreSQL 的秘密武器。它比大多数 NoSQL 查询速度更快,而且能保持数据一致性。

四、全文检索

Elasticsearch 集群成本高昂且复杂,而 PostgreSQL 内置的全文搜索功能非常出色:

-- 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;

它开箱即用,支持模糊匹配、词干提取和相关性排序。

在 UserJot 的反馈搜索功能中,用户可立即通过标题、描述和评论中找到所需的功能请求,无需 Elasticsearch 集群,纯粹依靠 PostgreSQL 发挥其核心优势即可实现。

五、实时功能

抛开复杂的 WebSocket 架构,PostgreSQL 的 LISTEN/NOTIFY 机制可为你提供实时更新,无需任何额外服务:

-- 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 发布或者订阅模式。

六、“专业化”工具的隐性成本

我们来算笔账,一个典型的“现代”堆栈的成本是:

  • Redis:每月 20 美元
  • 消息队列:每月 25 美元
  • 搜索服务:每月 50 美元
  • 3 项服务的监控费用:每月 30 美元
  • 总计:每月 125 美元

但这只是主机托管费用,真正的痛点在于:

1、运营费用

  • 三项不同的服务需监控、更新和调试
  • 不同的扩展模式和故障模式
  • 维护多种配置
  • 独立的备份和灾难恢复程序
  • 每项服务的安全考虑因素各不相同

2、开发复杂性

  • 不同的客户端库和连接模式
  • 协调跨多个服务的部署
  • 系统间数据不一致
  • 复杂的测试场景
  • 不同的性能调优方法

如果你选择自建服务器,那么还需进行服务器管理、安全补丁,以及在 Redis 占用全部内存时不得不在凌晨 3 点进行调试。

但 PostgreSQL 通过单一服务即可处理所有这些事务,该服务本就在你的管理范围内。

七、可扩展的单一数据库

大多数人可能没有意识到:单个 PostgreSQL 实例就能处理海量数据。我们说的是每天数百万笔交易、数 TB 的数据以及数千个并发连接。

实际案例:

  • Airbnb:单个 PostgreSQL 集群处理数百万笔预订
  • Robinhood:数十亿笔金融交易
  • GitLab:基于 PostgreSQL 的完整 DevOps 平台

PostgreSQL 的魅力在于其架构,它具备极强的垂直扩展能力,而当你最终需要水平扩展时,也有很多成熟的方案可选择,例如:

  • 读取副本以进行查询扩展
  • 分区处理大型表
  • 连接池实现并发
  • 分布式架构的逻辑复制

大多数企业永远不会遇到这些限制。除非你需要处理数百万用户或复杂的分析工作负载,否则单个实例可能就足够了。

相比之下,管理那些扩展能力不一的独立服务则截然不同:你的 Redis 可能内存已达上限,消息队列可能吞吐量不足,而搜索服务则需要完全不同的硬件配置。

八、从一开始就停止过度设计

现代开发的最大陷阱,莫过于架构空想。我们总在为尚未出现的问题设计系统,针对从未遇到的流量做方案,为可能永远达不到的规模做准备。

1、过度设计循环

  1. “我们或许有一天需要扩大规模”;
  2. 添加 Redis、队列、微服务和多个数据库;
  3. 花费数月时间调试集成问题;
  4. 面向 47 位用户发布;
  5. 每月支付 200 美元购买的基础设施,其实只需一台 5 美元的 VPS 就能运行;

与此同时,你的竞争对手交付速度更快。因为他们不会在真正需要分布式系统之前,就盲目投入精力去搭建和维护它。

2、更好的方法

  1. 从 PostgreSQL 开始,简单起步;
  2. 监控实际存在的瓶颈,而不是臆想出来的瓶颈;
  3. 当达到实际限制时,调整特定组件的规模;
  4. 仅在方案能解决实际问题时,才引入复杂设计。

你的用户并不关心你的架构,他们只关心你的产品是否好用,能否解决他们的问题。

九、当你真正需要专用工具时

专用工具自有其用处,但可能只有出现以下情况才用到它们:

  • 每分钟处理超过 10 万个作业;
  • 需要亚毫秒级的缓存响应;
  • 正在对 TB 级的数据进行复杂的分析;
  • 拥有数百万并发用户;
  • 需要满足特定一致性要求的全球数据分发。

十、为什么这真的很重要

最让我震惊的是:PostgreSQL 可以同时作为主数据库、缓存、队列、搜索引擎和实时系统,而且还能在所有组件间保持 ACID 事务。

-- One transaction, multiple operations
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 之间执行这样的操作,看你能不能不崩溃。

十一、无聊的技术却能获胜

PostgreSQL 并不引人注目,它既没有花里胡哨的官网,也没有像 TikTok 那样爆红的平台。但数十年来,当其他数据库不断迭代更替时,它始终在背后默默支撑着互联网的运转。

选择这类朴实可靠、能稳定落地的技术,本身就很有讲究。

十二、下一个项目的行动步骤

  1. 先只使用 PostgreSQL 开始:不要急于添加其他数据库;
  2. 使用 JSONB 实现灵活性:既能享受无模式的优势,又能拥有 SQL 的强大功能;
  3. 在 PostgreSQL 中实现队列:节省成本并降低复杂性;
  4. 真正遇到瓶颈时才添加专用工具:注意,不是想象中的瓶颈。

十三、我的真实经历

UserJot 的开发正是对这一理念的完美检验。作为一款反馈与路线图工具,它需要:

  • 提交反馈后实时更新;
  • 对数千个功能请求进行全文搜索;
  • 用于发送通知的后台任务;
  • 为频繁访问的路线图提供缓存;
  • 存储用户偏好和设置的键值存储。

我的整个后端仅由单个 PostgreSQL 数据库构成。没有 Redis,没有 Elasticsearch,也没有消息队列。从用户身份验证到实时 WebSocket 通知,一切都由 PostgreSQL 处理。

结果如何?我可以更快地发布功能,需要调试的组件更少,基础设施成本也降到了最低。所有底层工作都由 PostgreSQL 完成:用户提交反馈、搜索功能或获取路线图变更的实时更新。

这早已不是纸上谈兵,而是承载着真实用户与业务数据,稳定运行于生产和环境。

十四、令人不安的结论

PostgreSQL 或许过于优秀反而成了负担。它功能如此强大,以至于让其他数据库在 90% 的应用场景中显得多余。行业惯例让我们相信每件事都需要专用工具,但或许我们只是把事情搞得比实际更复杂。

初创公司不需要成为分布式系统的展示平台,它需要解决真实用户面临的实际问题。PostgreSQL 让你能够专注于此,而不是一直在维护基础设施。

所以下次如果有人提议添加 Redis “提升性能”或添加 MongoDB “增强灵活性”时,不妨反问:“你是否尝试过先用 PostgreSQL 实现?”

答案或许会让你惊讶。当我将 UserJot 完全构建在 PostgreSQL 之上时也感到非常意外,而它至今运行得无比顺畅。

希望这篇文章能为你提供一个不同的技术选型视角。如果你对类似的技术深度探讨感兴趣,欢迎在 云栈社区 查看更多相关内容。




上一篇:Python状态机实现详解:Transitions库入门与订单状态管理实战
下一篇:MySQL CPU 100%故障全链路紧急处置指南(含脚本与案例)
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-1-14 16:01 , Processed in 0.428397 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表