你的 Microservices 不可扩展。你的 Database 正在哭泣。

发布: (2026年2月5日 GMT+8 05:24)
6 min read
原文: Dev.to

Source: Dev.to

隐藏的瓶颈

我们最初把一切都归咎于显而易见的东西之外:“也许我们需要更多副本。”
事实更简单,也更让人不舒服:我们的微服务并不是问题所在。

微服务卖的是一个诱人的理念——让系统的每个部分都可以独立扩展。实际上,大多数团队的做法是:

  1. 将应用拆分成 10–20 个服务。
  2. 把它们全部指向同一个数据库。
  3. 称之为 “微服务架构”。

结果是一个 分布式单体,伴随网络延迟。每个服务可以水平扩展,但所有流量仍然汇聚到同一个瓶颈。负载上升时,数据库出现混乱,而不是微服务本身。

症状

  • 延迟突增,但没有错误或崩溃。
  • 连接数增多、只读副本延迟、连接池耗尽。
  • 锁堆积在无人监控的地方。

看似无害的单独改动,组合在一起会变成灾难:

服务改动额外查询
A新增端点+3 条查询
B“只加个 join”+2 条查询
C每 5 秒轮询一次

扩展的影响

把一个服务从 2 个 pod 扩展到 20 个 pod,不只是吞吐量的线性增长;它会成倍增加:

  • 打开的连接数
  • 空闲事务
  • 并发写入
  • 缓存未命中
  • 锁争用

数据库把每个 pod 当作一个新来的陌生人,积极请求资源,即使仪表盘上显示 “服务延迟看起来还好”。

缓存的诱惑

大多数团队会加入:

  • 用于读取的 Redis
  • 带有情感化 TTL 的 HTTP 缓存

缓存让系统变快……直到它不再快,因为:

  • 写操作仍然落在同一个数据库上
  • 缓存失效很快变得混乱
  • 跨服务的数据一致性变成猜谜游戏
  • 运维复杂度上升,却没有消除耦合

缓存是止痛药,而不是根治方案。

未能解决的问题

  • 更大的数据库实例
  • 更多副本
  • 更高的连接上限
  • 在站会上大喊 “优化查询”

有效的做法

每个服务拥有自己的数据。 这点必须坚持。

如果另一个服务需要这些数据,它必须:

  • 调用 API,
  • 消费事件,
  • 从专门构建的读模型中读取

不要出现 “只要跨服务一次 join”。这种模式只会让数据库的痛点重新燃起。

我们用以下方式替换了同步依赖:

  • 事件
  • 异步工作流
  • 最终一致性更新

并不是所有东西都必须瞬时完成;大多数系统只需要可靠。

思维方式的转变

我们不再问 “这个服务能扩展吗?” 而是问 “在流量提升 10 倍时,这会对数据库产生什么影响?” 这唯一的问题重新塑造了我们的架构评审。

微服务并不会自动带来可扩展性。它们提供了选项——但代价是纪律。没有严格的边界,它们会放大数据库问题,而不是解决它们。

要点

  • 拥有自己的数据。 每个服务应拥有自己的 schema 或数据库。
  • 避免共享表,跨服务共享表会产生隐藏耦合。
  • 为流量模式设计。 理解 pod 扩展如何成倍增加数据库负载。
  • 优先使用异步通信 而非同步 join。
  • 将数据库健康(连接数、复制延迟、锁争用)视为一等关注点进行监控。

如果你的系统在流量增加时变慢,不要只盯着服务本身。请检查:

  1. 谁拥有数据?
  2. 有多少服务触及相同的表?
  3. pod 扩展如何成倍增加数据库负载?
  4. 你的架构是否匹配流量模式?

因为十有八九,当 “微服务无法扩展” 时……其实是微服务在扩展,只是你的数据库在哭求帮助。

Back to Blog

相关文章

阅读更多 »

实现 gRPC.

gRPC 是由 Google 开发的框架,提供一种高效、语言无关的机制,用于进行远程过程调用(RPC)。它的主要使用场景……