使用Django简化分片

Min*_*ark 21 django postgresql sharding instagram

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

我希望用户分片跨使用相同的数据库服务器通过Instagram的使用分片逻辑:

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

  • 逻辑分片ID直接根据用户ID计算(嵌入在用户ID中的13位).
  • 从逻辑到物理分片ID的映射是硬编码的(在某些配置文件或静态表中).
  • 从物理分片ID到数据库服务器的映射也是硬编码的.Instagram此时使用Pgbouncer来检索与相应数据库服务器的池化数据库连接.
  • 每个逻辑分片都存在于自己的PostgreSQL模式中(对于那些不熟悉PostgreSQL的人来说,这不是表模式,它更像是一个名称空间,类似于MySQL'数据库').模式简单地命名为"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)
Run Code Online (Sandbox Code Playgroud)

获取相关对象

# this gets the user's posted articles, located in the same logical shard:
articles = user.articles
Run Code Online (Sandbox Code Playgroud)

创建实例

# 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()
Run Code Online (Sandbox Code Playgroud)

按名称搜索用户

# 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")
Run Code Online (Sandbox Code Playgroud)

为了使事情变得更复杂,我使用Streaming Replication将每个数据库服务器的数据复制到多个从属服务器.主设备应该用于写入,从设备应该用于读取.

Django提供了对自动数据库路由的支持,这可能足以满足上述大部分需求,但我坚持认为User.objects.get(pk = user_id)因为路由器无法访问查询参数,所以它不知道用户ID是什么,它只知道代码试图读取用户模型.

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

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

非常感谢您的帮助.

注意

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

Str*_*ter 6

Mike Clarke最近在PyPgDay上就如何使用Django和PostgreSQL对用户进行分片进行了讨论.他写了一篇关于他们如何做的博客文章.

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

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


Ric*_*ton 2

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

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

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