在分片中跨多个数据库排序

Order by across multiple database in sharding

假设我们正在开发一个拥有数十亿用户的 Instagram。我们在多个数据库中对照片 table 进行分片(在不同的分片 instances/servers/devices 中),并且在照片 table 中我们有一个 createdAt 列。现在用户在应用程序中打开主页选项卡,应用程序应该显示最近的 20 张照片 (order by createdAt desc) globally(not locally) across the photo table在多个数据库中。 SQL 查询应该如何?

我们必须对照片进行分片 table,因为数十亿用户会制作出数千亿张照片。我们无法在一台服务器的一个数据库中的一个 table 中存储和提供数千亿张照片。

假设我们有 100 台数据库服务器,一种可能的解决方案是查询 select id from photo order by createdAt desc limit 20 超过 100 台数据库服务器的照片 table。然后在我们的后端,我们得到 20*100 = 2000 张照片行,并在后端按 createdAt(Node.js、Java、Python 等)和 return 对它们进行排序前 20 行。

听起来您要找的是 Spider storage engine from MariaDB。 这将使您在不同的服务器上拥有每个分区。您应该意识到,像这样的架构永远不会完全透明 - 要从中获得最佳(甚至良好)性能,您必须围绕底层数据存储的性能副作用来设计整个应用程序。

如果按用户拆分数据库服务器是此 table 的逻辑映射,则在应用程序中应用映射(最好是不需要数据库查找的映射),然后直接使用该数据库服务器 SELECT .. FROM photos ORDER BY createdAt DESC

现在谈论分片还为时过早。在你的数据集中有数百万个条目之前不要考虑它。

到那时,您将至少重新设计一次架构。只有在第二次或第三次重新设计之后,您才应该担心分片。比如...

到达那里后,这里有一些提示:

  • 一个 table(或一小群密切相关的tables)将被拆分到多台机器("sharding")。
  • 其他 tables 将需要在分片中复制,或保存在单独的机器上。维护这些 table 成为一项单独的管理任务。
  • 它将被一些 "id" 分片。您对 id 的选择可能需要更改;但不要详述它。 UUID 存在性能问题,但让多个客户端独立构造唯一的 id。有更好的方法;稍后回电。
  • 您将需要多层机器——用于数据库、Web 服务器、路由器等。
  • 需要查看所有分片的查询写起来会很复杂 并且 会慢到 运行。所以尽量避免这样。
  • 分片可以通过哈希或字典或两者的混合来完成。
  • 编写一个工具将用户从一个分片迁移到另一个分片。该工具是简化许多任务的关键——硬件升级、软件升级、崩溃修复、负载平衡等。
  • 将照片放在不同的服务器上;只在数据库中保留 URL。这可以简化事情,更有效地利用硬件等。
  • 100B 照片,每张 1MB -- 这将需要 许多 标准机器或几个巨大的 SAN。保持它独立于数据库可以让您单独扩展它。
  • “所有分片中的 20 张最新照片”——建议您使用具有 API 的非分片服务器,其主要目的是接收 URL 并维护该列表;加上提供清单。这可能是一台服务器可以处理的全部。并且一直触及所有分片可能会使整个系统崩溃。
  • 您将需要数百台服务器来满足您的描述;你的预算是多少?您的 HA 要求是什么?数百台机器 == 每隔几天就有一台崩溃。并且您将需要每隔几天添加另一台服务器以增加容量。您将招聘多少 SA/DBA IT 专家?

Flickr 是多年前在分片 MySQL 服务器上构建的。所以,这是可能的。他们有一个 "group",其唯一目标是上传一百万张图片。 "whale" 给了他们一些挑战。

从每个数据库中获取前 20 行并在应用程序内存中排序的简单方法。 有更好的解决方案,可以避免使用数据库的游标将所有 20*100=2000 个数据一起加载到内存中。因为每个数据库的所有数据都是有序的,我们可以只比较当前游标的数据,将最小(或最大,ASC或DESC的依赖)数据保留在获取的数据中,然后用游标调用next。每个 next 只需要调用 real next 一次。它被称为 stream order by.

有点复杂,幸好Apache ShardingSphere完成了数据分片功能,并使用smart order by merge来处理上述算法。

预估:https://shardingsphere.apache.org/document/current/en/features/sharding/principle/merge/#order-by-merger