数据库分片、反规范化和同步

Database sharding, denormalization and synchronization

在分片中,建议遵循不共享,分片一切的方法。从本质上讲,这意味着:要一起使用的数据要存储在一起(即在单个分片中)。这非常符合在应用程序级别拆分数据的理念。

但是完全非规范化数据并不总是可行的。以电子商务网站为例。理想情况下,与用户对应的所有数据都应该保存在一起。但是,某些数据(例如产品可用性)需要始终同步。在某些情况下,就像前面提到的那样,这种同步需要实时发生。例如,假设用户已将产品添加到他们的愿望清单中。原则上,有关愿望清单项目的所有数据都应与用户的其余数据一起保存。但是,多个用户可以将同一商品列入愿望单,而其他用户也可以购买该商品,从而影响其可用性。因此,需要以某种方式共享和同步信息。

多重连接带来的复杂性和性能损失也是众所周知的。

为了使问题更加棘手,预计在上面的示例中,或者在任何需要适当的 ACID 事务的情况下,同步实际上必须是实时的。如果延迟更新点赞数量可能是可以接受的,但电子商务网站显示延迟的产品可用性数据将是一项糟糕的业务!

在这种情况下最好的方法是什么?

一个初步的想法是对可用性、交易状态等字段使用 push/notification 机制。但我真的很想听听专家的意见。显然,我已经在 High Scalability 上阅读了有关 eBay 架构的信息,但它并未涉及这一级别的实施细节。

dba.stackexchange 上有一个相关的相关讨论,但问题多于答案。

EDIT/UPDATE: 正在考虑的数据库是 Postgres。

您没有具体说明您正在查看的任何数据库,所以我将讨论一些真正高端的格框架如何在 PostgreSQL 上解决这个问题。如果不出意外,这为您提供了答案的起点。

出于本次讨论的目的,网格框架是一个实质上具有一系列看起来像单个数据库的协调分片的框架。可以说存在一些差异,特别是在工具方面,但它们遇到的问题与您提出的问题完全相同。格通过两阶段提交等方式管理存储节点,允许协调器有效地实施跨分片参照完整性。 Pg界最常用的框架是Postgres-XL

使用 Postgres-XL(以前称为 StormDB),您可以在协调器和存储节点之间进行划分。每个存储节点实际上是一个分片。协调器节点管理对存储节点的访问,并将整个存储节点集呈现为一个单一的连贯数据库。

几点:

  1. 在这种框架中,跨分片外键 昂贵 原因有很多,包括连接性能和引用完整性实施。所以好的设计可以避免这些。
  2. 跨分片外键的解决方案涉及重大权衡。

在这种情况下,您的选择是要么只接受跨节点性能损失,要么同步数据。如果你选择后者,你的写入将永远不会比你最慢的节点快,所以你不想对频繁写入的数据执行此操作。

这实际上意味着您必须确定哪些数据被频繁写入,哪些大部分是稳定的。可以同步稳定的数据。易失性数据不应该。

所以在电子商务解决方案中,如果您的零件目录非常稳定,您可以同步它,然后分片客户和订单。然而,零件的实时现有数据不会在主机之间复制,而是单独复制 sharded/partitioned,因此对此的更新也可以写扩展。因此,有时您必须考虑将现有表分解为稳定部分和易变部分。