我有一个基于多个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 方式)。