别堆砌中间件充门面:我们砍掉Redis/Kafka/ES,整套业务只用PostgreSQL落地实践

📅 2026/7/18 4:54:58
别堆砌中间件充门面:我们砍掉Redis/Kafka/ES,整套业务只用PostgreSQL落地实践
引言很多技术团队存在一种技术误区把基础设施的丰富性当成炫耀项目的资本架构里塞满Redis、Kafka、Elasticsearch觉得技术栈越丰富、组件越多项目越专业、越有扩展性。但现实往往截然相反——多一套中间件就多一套监控、备份、故障预案、版本升级、运维告警系统复杂度指数级上涨。其实同时维护Redis、Kafka、ES、PostgreSQL四套存储每月34次告警、3000元基础设施开销三名工程师大半精力耗费在维护中间件而非开发客户核心功能。最终团队做出颠覆性决策移除三大中间件所有能力全部交由已存在的PostgreSQL承载。迁移后成本腰斩、告警锐减每周凭空多出14个小时研发人力投入业务迭代。本文结合该个人团队真实迁移方案重新封装业务数据表、拆解替换逻辑结合后端开发视角分析「过早引入专业中间件」的行业通病同时客观界定PostgreSQL的能力边界区分什么场景适合简化架构、什么场景必须保留专用组件。一、臃肿架构的隐性代价多存储带来的系统性隐患原四层存储架构应用服务同时对接Redis、Kafka、ES、PostgreSQL覆盖缓存、消息推送、异步任务、全文检索四大能力看似分工清晰实则埋下多重长期隐患。多数据源数据一致性无法保障数据库、缓存、索引、消息队列各自持有一份业务数据无法在同一事务内完成变更。写入数据库后缓存更新延迟、ES索引同步滞后、消息丢失等问题频发衍生大量偶发、难以复现的隐性bug长期消耗团队排查精力。运维人力被大量占用四套存储独立部署、独立监控、独立备份策略、独立故障处理流程。Redis内存溢出、Kafka分区堆积、ES分片失衡、集群断连等问题轮番触发告警工程师每周固定拿出18小时处理基础设施问题积压需求长期无法推进。无意义的性能冗余团队峰值消息仅800条/分钟、检索数据量40万条完全达不到Kafka、ES、Redis的性能上限引入高性能中间件只是提前背负复杂度性能优势完全无法发挥。多数创业公司、中小型SaaS、内部业务系统都会陷入同类误区盲目对标大厂技术栈忽略自身真实业务流量为了“架构好看”提前引入重型中间件属于典型过早优化。二、分模块迁移方案PostgreSQL替代三大中间件2.1 Redis 替换缓存实时消息推送原Redis承担两大核心工作查询结果缓存、用户会话存储、基于Pub/Sub的前端实时通知。1缓存层物化视图进程内存缓存替代Redis缓存放弃独立缓存库高频统计、列表分页数据采用定时刷新物化视图低频会话数据使用Go内置sync.Map带内存TTL本地缓存规避网络IO无需维护Redis集群、解决缓存雪崩、内存溢出、缓存与数据库双写不一致等经典问题。2实时通知LISTEN/NOTIFY 触发器替代Pub/Sub自定义通知触发器表biz_real_notify数据插入后自动触发pg_notify推送事件应用端通过pgx长连接监听频道实现低延迟实时推送。CREATEORREPLACEFUNCTIONtrigger_push_notify_event()RETURNStriggerAS$$BEGINPERFORM pg_notify(notify_channel_||NEW.target_uid::text,row_to_json(NEW)::text);RETURNNEW;END;$$LANGUAGEplpgsql;CREATETRIGGERafter_notify_insertAFTERINSERTONbiz_real_notifyFOR EACH ROWEXECUTEFUNCTIONtrigger_push_notify_event();Go应用监听逻辑ctx:context.Background()conn,err:pgx.Connect(ctx,dsn)iferr!nil{returnerr}deferconn.Close(ctx)// 监听指定用户频道_,_conn.Exec(ctx,fmt.Sprintf(LISTEN notify_channel_%s,userId))for{notify,err:conn.WaitForNotification(ctx)iferr!nil{break}handleUserNotify(notify.Payload)}延迟从Redis 1ms提升至3~5ms但业务场景为前端定时刷新仪表盘毫秒级差异用户完全无感知省去Redis客户端、集群扩容、内存告警全套运维成本。2.2 Kafka 替换任务队列表实现异步消费以前我们主观认为消息队列必须使用专业流处理组件。实际业务峰值仅800条/分钟完全可以依靠PostgreSQL行级锁实现可靠任务队列。新建异步任务表biz_async_task通过SKIP LOCKED实现多worker无阻塞并发抢占任务天然规避重复消费、消息丢失依托数据库事务保证任务与业务数据一致性。CREATETABLEbiz_async_task(id BIGSERIALPRIMARYKEY,task_typeTEXTNOTNULL,task_payload JSONBNOTNULL,task_statusTEXTNOTNULLDEFAULTpending,execute_at TIMESTAMPTZDEFAULTNOW(),lock_time TIMESTAMPTZ,worker_tagTEXT);-- 联合索引加速待消费任务筛选CREATEINDEXidx_task_pendingONbiz_async_task(task_type,task_status,execute_at)WHEREtask_statuspending;worker原子抢占任务SQL多进程并发无竞争阻塞UPDATEbiz_async_taskSETtask_statusrunning,lock_timeNOW(),worker_tag$1WHEREid(SELECTidFROMbiz_async_taskWHEREtask_type$2ANDtask_statuspendingANDexecute_atNOW()ORDERBYexecute_atASCFORUPDATESKIP LOCKEDLIMIT1)RETURNINGid,task_payload;测试单库双worker每分钟稳定处理1200条任务远超业务峰值具备充足性能冗余。相比Kafka省去分区、消费者组、消息堆积、日志清理、同步备份一系列运维工作。2.3 Elasticsearch 替换原生全文检索模糊匹配原有ES仅用于商品名称、描述检索、分类价格过滤、相关性排序无复杂多维聚合、自定义分词器等高阶需求PostgreSQL内置tsvectorpg_trgm完全覆盖。给商品业务表biz_product生成持久化检索向量搭配GIN索引大幅提升检索速度ALTERTABLEbiz_productADDCOLUMNsearch_index_vec tsvector GENERATED ALWAYSAS(to_tsvector(english,COALESCE(name,)|| ||COALESCE(desc,)))STORED;-- 全文检索索引CREATEINDEXidx_product_search_vecONbiz_productUSINGGIN(search_index_vec);-- 模糊匹配索引CREATEINDEXidx_product_name_trgmONbiz_productUSINGGIN(name gin_trgm_ops);检索查询语句支持关键词匹配、分类过滤、相关性权重排序SELECTid,name,ts_rank(search_index_vec,query)ASmatch_rankFROMbiz_product,to_tsquery(english,$1)queryWHEREsearch_index_vec queryANDcategory_id$2ORDERBYmatch_rankDESCLIMIT20;40万条商品冷查询平均30ms缓存热数据下中位数8ms虽然p99延迟高于ES但完全满足后台检索、商户查询业务需求。三、简化架构落地后真实数据对比新旧架构并行运行六周后完全下线中间件量化收益直观体现简化架构的价值指标多中间件架构纯PostgreSQL架构变化分析月度基础设施成本4200美元1800美元砍掉Redis、Kafka、ES三套集群服务器成本削减57%月度告警次数34次7次仅保留数据库基础监控消除中间件各类异常告警每周运维耗时18小时4小时每周释放14小时研发人力回归业务功能开发检索p99延迟22ms41ms小幅性能衰减业务无感知通知推送p99延迟1ms6ms延迟小幅上涨不影响前端交互团队工程负责人最在意的并非成本降低而是每周多出的14小时研发时间。迁移完成后团队直接落地积压8个月的客户核心需求客户反馈显著提升——这是单纯性能指标无法衡量的长期收益。简化后架构极简应用服务仅对接一套PostgreSQL缓存、消息、任务、检索全部依托数据库内置能力实现统一备份、统一监控、统一故障排查流程出现问题无需跨多组件定位。四、客观边界不是所有场景都适合砍掉中间件本文方案核心思想是拒绝无意义的架构复杂化而非全盘否定Redis、Kafka、Elasticsearch必须清晰划分适用边界适合仅用PostgreSQL的场景中小型SaaS、内部管理系统、数据监测平台如雷达PDF业务峰值流量数千/分钟以内对延迟无亚毫秒硬性要求可接受5~50ms区间响应追求低运维成本、小团队无专职中间件运维工程师需要强数据一致性无法容忍多数据源数据偏差。必须保留专用中间件的场景Kafka海量事件流、多独立消费者、需要长期消息回放、每秒数万条消息峰值Elasticsearch海量日志检索、复杂多维聚合、自定义分词、上亿级数据全文检索Redis核心前台高并发秒杀、百万QPS、硬性要求亚毫秒延迟、大规模内存计数器。绝大多数中小团队的业务流量远达不到需要专用中间件支撑的规模提前引入只会徒增负担。盲目照搬大厂架构本质是没有基于自身业务负载做技术选型。结语基础设施的价值是支撑业务而非用来展示技术广度。不用为了架构看上去“专业”堆砌Redis、Kafka、Elasticsearch。当业务体量尚未达到专用中间件的性能门槛PostgreSQL完全可以一站式承载缓存、消息、异步任务、全文检索全部能力大幅降低运维复杂度、释放研发人力。技术优雅的本质不是组件繁多而是恰到好处的简单。只有当业务负载明确证明单库无法支撑时再按需引入专业中间件才是成熟、务实的架构选型思路。