1. 中间件概述

1.1 什么是数据库中间件

数据库中间件是位于应用层与数据库层之间的独立服务层,负责对数据库访问进行统一管理、路由、连接调度与流量治理。在 PostgreSQL 生态中,中间件通常承担以下核心职责:

  • 连接管理:复用客户端连接,减少后端数据库的连接开销。
  • 读写分离:将查询请求分发到只读副本,减轻主库压力。
  • 分片路由:按分片键将数据分布到多个 PostgreSQL 实例。
  • 熔断与限流:防止突发流量击穿数据库。
  • 幂等保障:对重复请求进行去重或状态校验,保证数据最终一致。
关键认知: 数据库中间件不是代理(Proxy)的简单替代,而是将连接池、路由、治理、可观测性整合为一的架构组件。在 PostgreSQL 生态中,PgBouncer、Pgpool-II、Citus、ShardingSphere-Proxy 等均属于此类。

1.2 中间件在微服务架构中的位置

在微服务架构中,每个服务通常拥有独立的数据库实例或 Schema,但共享中间件层进行统一接入。下图展示了中间件在微服务调用链中的典型位置:

数据库中间件在微服务架构中的位置 数据库中间件在微服务架构中的位置 服务 A 服务 B 服务 C 数据库中间件层(连接池 + 路由 + 幂等) PgBouncer / Pgpool-II / ShardingSphere-Proxy PostgreSQL 主库 PostgreSQL 从库 PostgreSQL 从库 微服务不直连数据库,所有 SQL 请求经过中间件层统一调度 连接池复用、读写分离、幂等去重均在中间件层完成
架构要点: 中间件层对微服务透明——服务端 SDK 无需感知后端拓扑变化。当主库切换、从库扩缩容时,仅需调整中间件配置,服务代码零改动。

1.3 为什么需要连接池与幂等

在微服务高并发场景下,PostgreSQL 的直接连接管理面临两个核心挑战:连接风暴 与 重复请求。连接池与幂等处理正是针对这两个问题的关键治理手段。

1.3.1 连接池的必要性

PostgreSQL 为每个客户端连接分配独立后端进程(fork 模式),连接数过多会导致:

  • 内存膨胀:每个连接占用约 2~10 MB 共享内存,2000 个连接即消耗 4~20 GB。
  • 上下文切换:大量进程争抢 CPU,TPS 反而下降。
  • 连接建立慢:TCP 握手 + SSL 协商 + 认证,单次耗时可达 10~50 ms。

连接池通过复用少量长连接,将应用层的并发请求排队发送到数据库,显著降低资源消耗。以下是连接池前后的对比:

指标 无连接池(直连) 有连接池(PgBouncer)
最大连接数 2000+(易超限) 200~500(可控)
连接建立延迟 10~50 ms / 次 0.1~0.5 ms(复用)
数据库内存开销 高(每连接 2~10 MB) 低(池内固定)
抗突发能力 弱(易 OOM 或拒绝) 强(排队 + 限流)

1.3.2 幂等处理的必要性

在分布式系统中,网络超时、重试机制、消息重复投递等场景会导致同一条 SQL 或事务被多次执行。对于非幂等操作(如 INSERT、UPDATE 累加、扣减库存),重复执行会造成数据不一致。

幂等处理的核心目标是:无论请求被提交多少次,最终状态与执行一次相同。在中间件层面实现幂等,可以避免业务代码侵入式地处理重复逻辑。

典型风险场景: 支付回调中,因网络抖动导致扣款请求被重发 3 次,若中间件未做幂等,用户账户将被多扣 2 次金额。幂等中间件通过唯一请求 ID 去重,确保只生效一次。

连接池与幂等的关系并非孤立——连接池提供稳定的连接复用环境,幂等处理在此基础上保证数据正确性。两者共同构成中间件层的“稳定 + 正确”双基石。

连接池与幂等的协同关系 连接池与幂等的协同关系 连接池(Connection Pool) 复用长连接,降低开销 排队请求,防止连接风暴 健康检查,自动剔除失效连接 连接数可控,数据库更稳定 幂等处理(Idempotency) 唯一请求 ID 去重 状态机校验(已处理则跳过) 事务级幂等标记 保证最终一致性 协同 连接池保障系统稳定性,幂等保障数据正确性,二者缺一不可

1.4 本章小结

概念 核心价值 在 PostgreSQL 中间件中的体现
数据库中间件 统一管理数据库访问,解耦应用与存储 PgBouncer、Pgpool-II、Citus、ShardingSphere-Proxy
连接池 复用连接,降低资源消耗,防止连接风暴 PgBouncer 的 session/transaction/mode 池
幂等处理 去重重复请求,保证数据最终一致 中间件层拦截重复 SQL,状态机校验