探索 Python/Django 支持分布式多租户数据库,如 Postgres+Citus

本文详细介绍了如何使用Django和django-multitenant库将多租户应用程序迁移到Citus分布式数据库。主要步骤包括:向模型引入租户列,修改主键和唯一约束,使用TenantModelMixin和TenantForeignKey,以及在Citus中分发数据。通过这些操作,可以实现多租户应用的水平扩展。
摘要由CSDN通过智能技术生成

image

在 确定分布策略 中,我们讨论了在多租户用例中使用 Citus 所需的与框架无关的数据库更改。 在这里,我们专门研究如何借助 django-multitenant 库将多租户 Django
用程序迁移到 Citus 存储后端。

此过程将分为 5 个步骤:

  • 将租户列介绍给我们想要分发的缺少它的模型
  • 更改分布式表的主键以包含租户列
  • 更新模型以使用 TenantModelMixin
  • 分发数据
  • Django 应用程序更新为范围查询

准备横向扩展多租户应用程序

最初,您将从放置在单个数据库节点上的所有租户开始。 为了能够扩展 django,必须对模型进行一些简单的更改。

让我们考虑这个简化的模型:

from django.utils import timezone
from django.db import models

class Country(models.Model):
    name = models.CharField(max_length=255)

class Account(models.Model):
    name = models.CharField(max_length=255)
    domain = models.CharField(max_length=255)
    subdomain = models.CharField(max_length=255)
    country = models.ForeignKey(Country, on_delete=models.SET_NULL)

class Manager(models.Model):
    name = models.CharField(max_length=255)
    account = models.ForeignKey(Account, on_delete=models.CASCADE,
                                related_name='managers')

class Project(models.Model):
    name = models.CharField(max_length=255)
    account = models.ForeignKey(Account, related_name='projects',
                                on_delete=models.CASCADE)
    managers = models.ManyToManyField(Manager)

class Task(models.Model):
    name = models.CharField(max_length=255)
    project = models.ForeignKey(Project, on_delete=models.CASCADE,
                                related_name='tasks')

这种模式的棘手之处在于,为了找到一个帐户的所有任务,您必须首先查询一个帐户的所有项目。 一旦您开始分片数据,这就会成为一个问题,特别是当您对嵌套模型(如本例中的任务)运行 UPDATEDELETE 查询时。

1. 将租户列引入属于帐户的模型

1.1 向属于某个帐户的模型引入该列

为了扩展多租户模型,查询必须快速定位属于一个帐户的所有记录。考虑一个 ORM 调用,例如:

Project.objects.filter(account_id=1).prefetch_related('tasks')

它生成这些底层 SQL 查询:

SELECT *
FROM myapp_project
WHERE account_id = 1;

SELECT *
FROM myapp_task
WHERE project_id IN (1, 2, 3);

但是,使用额外的过滤器,第二个查询会更快:

-- the AND clause identifies the tenant
SELECT *
FROM myapp_task
WHERE project_id IN (1, 2, 3)
      AND account_id = 1;

这样您就可以轻松查询属于一个帐户的任务。 实现这一点的最简单方法是在属于帐户的每个对象上简单地添加一个 account_id 列。

在我们的例子中:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值