26

我有一个基于多个PostgreSQL服务器的Django项目。

我希望用户使用Instagram使用的相同分片逻辑在这些数据库服务器上进行分片:

用户 ID => 逻辑分片 ID => 物理分片 ID => 数据库服务器 => 架构 => 用户表

  • 逻辑分片 ID 直接根据用户 ID(嵌入在用户 ID 中的 13 位)计算得出。
  • 从逻辑分片 ID 到物理分片 ID 的映射是硬编码的(在某些配置文件或静态表中)。
  • 从物理分片 ID 到数据库服务器的映射也是硬编码的。Instagram 此时使用Pgbouncer来检索与适当数据库服务器的池化数据库连接。
  • 每个逻辑分片都存在于自己的PostgreSQL 模式中(对于那些不熟悉 PostgreSQL 的人,这不是表模式,它更像是一个命名空间,类似于MySQL 'databases')。该模式被简单地命名为“shardNNNN”,其中 NNNN 是逻辑分片 ID。
  • 最后,查询相应模式中的用户表。

如何在 Django 中尽可能简单地实现这一点?

理想情况下,我希望能够编写 Django 代码,例如:

获取实例

# this gets the user object on the appropriate server, in the appropriate schema:
user = User.objects.get(pk = user_id)

获取相关对象

# this gets the user's posted articles, located in the same logical shard:
articles = user.articles

创建实例

# this selects a random logical shard and creates the user there:
user = User.create(name = "Arthur", title = "King")
# or:
user = User(name = "Arthur", title = "King")
user.save()

按名称搜索用户

# fetches all relevant users (kings) from all relevant logical shards
# - either by querying *all* database servers (not good)
# - or by querying a "name_to_user" table then querying just the
#   relevant database servers.
users = User.objects.filter(title = "King")

为了让事情变得更加复杂,我使用流式复制将每个数据库服务器的数据复制到多个从属服务器。master 应该用于写入,slave 应该用于读取。

Django 提供了对自动数据库路由的支持,这对于上述大多数情况来说可能已经足够了,但是我被困住了,User.objects.get(pk = user_id)因为路由器无法访问查询参数,所以它不知道用户 ID 是什么,它只知道该代码正在尝试读取用户模型。

我很清楚,分片可能只应作为最后的优化手段使用,因为它有局限性并且确实使事情变得相当复杂。大多数人不需要分片:优化的主/从架构可以走很长的路。但是让我们假设我确实需要分片。

简而言之:如何尽可能简单地在 Django 中对数据进行分片?

非常感谢您的帮助。

笔记

存在一个非常相似的问题,但恕我直言,它太笼统了,缺乏精确的例子。我想将事情缩小到我感兴趣的特定分片技术(Instagram 方式)。

4

3 回答 3

9

Mike Clarke 最近在 PyPgDay 上发表了关于 Disqus 如何使用 Django 和 PostgreSQL 对用户进行分片的演讲。他写了一篇关于他们如何做到这一点的博客文章。

在对 Postgres 数据库进行分片时,可以采用多种策略。在 Disqus,我们选择基于表名进行分片。由于 Django 生成的原始表名可能是 comments_post,我们的分片工具将重写 SQL 以查询表 comments_post_X,其中 X 是基于一致哈希方案计算的分片 ID。所有这些表都存在于单个数据库实例上的单个模式中。

此外,他们发布了一些代码作为示例应用程序的一部分,展示了他们如何分片。

于 2013-04-09T15:40:34.163 回答
2

你真的不想处于问这个问题的位置。如果您按用户 ID 进行分片,那么您可能不想按名称搜索。

如果您对数据库进行分片,那么它不会对您的应用程序不可见,并且可能最终需要更改架构。

您可能会发现SkyTools很有用 - 阅读PL/Proxy。这就是 Skype 对他们的数据库进行分片的方式。

于 2012-08-02T20:51:17.547 回答
0

最好使用专业的分片中间件,例如:Apache ShardingSphere。

该项目包含 2 个产品,用于 java 驱动程序的 ShardingSphere-JDBC 和用于所有编程语言的 ShardingSphere-Proxy。它也可以支持 python 和 Django。

于 2021-10-13T16:24:13.520 回答