Citus多租户

数据库多租户

什么是多租户

多租户指一套系统能够支撑多个租户。一个租户通常是具有相似访问模式和权限的一组用户,典型的租户是同一个组织或者公司的若干用户。

权衡不同的多租户实现方式时,需要考虑如下因素:
扩展性:租户数量级别,以及未来发展趋势
安全性:租户之间数据隔离级别要求
资源共享:多租户通常有某种形式的资源共享
灵活性:不同租户可能有不同的需求,对特定租户需求的扩展能力
跨租户分析和优化:对全部租户或者多个租户的数据和行为进行分析的能力
运维和管理:运维管理的复杂度和便宜性,包括监控、修改数据库模式、创建索引、收集统计数据、数据加载等
成本:总体拥有成本,包括方案实现成本、运维成本等

多租户模型

一租户对应一数据库

最简单的多组户模型,为每一个用户创建一个数据库集群。

一租户对应一名字空间(模式)

多个租户共享同一个数据库,每个租户拥有独立的名字空间(或模式)。

全共享方式

不同租户共享同一个数据库、同一个名字空间。不同租户的数据在同一组表中共存,通过租户id标记和访问不同租户的数据
Citus采用此种多组户模型

read more about multi tenant

Citus多租户用例

多组户应用中,通常的SQL都包含租户ID。

创建表

CREATE TABLE companies (
    id bigint NOT NULL,
    name text NOT NULL,
    image_url text,
    created_at timestamp without time zone NOT NULL,
    updated_at timestamp without time zone NOT NULL
);

CREATE TABLE campaigns (
    id bigint NOT NULL,
    company_id bigint NOT NULL,
    name text NOT NULL,
    cost_model text NOT NULL,
    state text NOT NULL,
    monthly_budget bigint,
    blacklisted_site_urls text[],
    created_at timestamp without time zone NOT NULL,
    updated_at timestamp without time zone NOT NULL
);

CREATE TABLE ads (
    id bigint NOT NULL,
    company_id bigint NOT NULL,
    campaign_id bigint NOT NULL,
    name text NOT NULL,
    image_url text,
    target_url text,
    impressions_count bigint DEFAULT 0,
    clicks_count bigint DEFAULT 0,
    created_at timestamp without time zone NOT NULL,
    updated_at timestamp without time zone NOT NULL
);

ALTER TABLE companies ADD PRIMARY KEY (id);
ALTER TABLE campaigns ADD PRIMARY KEY (id, company_id);
ALTER TABLE ads ADD PRIMARY KEY (id, company_id);

设置分发列

分发列设置非常重要
在此多组户模型中,我们使用公司id作为分发列或称为多组户的用户id

SELECT create_distributed_table('companies', 'id');
SELECT create_distributed_table('campaigns', 'company_id');
SELECT create_distributed_table('ads', 'company_id');

执行SQL

  • 创建一个id为5000的租户
INSERT INTO companies VALUES (5000, 'New Company', 'https://randomurl/image.png', now(), now());
  • 更新id为5的租户的数据
UPDATE campaigns
SET monthly_budget = monthly_budget*2
WHERE company_id = 5;

在事务中运行:
BEGIN;
DELETE from campaigns where id = 46 AND company_id = 5;
DELETE from ads where campaign_id = 46 AND company_id = 5;
COMMIT;
  • 查询分析
    • 简单查询
SELECT name, cost_model, state, monthly_budget
FROM campaigns
WHERE company_id = 5
ORDER BY monthly_budget DESC
LIMIT 10;
  • 复杂查询
SELECT campaigns.id, campaigns.name, campaigns.monthly_budget,
       sum(impressions_count) as total_impressions, sum(clicks_count) as total_clicks
FROM ads, campaigns
WHERE ads.company_id = campaigns.company_id
AND campaigns.company_id = 5
AND campaigns.state = 'running'
GROUP BY campaigns.id, campaigns.name, campaigns.monthly_budget
ORDER BY total_impressions, total_clicks;
文章浏览总量 244 次

评论 (1)

  • liuhaifeng| 2019年9月25日

    非常棒

  • 要发表评论,您必须先登录