下端(500テナント/ 10000ユーザー)では、これが私がやった方法です。まず、グローバルで中央の「コントロール」データベースがあり、テナントとユーザーに関するすべての情報が含まれています(これらをSQL authログインとして管理したいとは本当に思わないでしょう)。したがって、次の表を持つ「Control」というデータベースを想像してください。
CREATE TABLE dbo.Instances
(
InstanceID INT PRIMARY KEY,
Connection VARCHAR(255)
--, ...
);
INSERT dbo.Instances SELECT 1, 'PROD1\Instance1';
INSERT dbo.Instances SELECT 1, 'PROD2\Instance1';
-- ...
CREATE TABLE dbo.Tenants
(
TenantID INT PRIMARY KEY,
Name NVARCHAR(255) NOT NULL UNIQUE,
InstanceID INT -- Foreign key tells which instance this tenant's DB is on
--, ...
);
INSERT dbo.Tenants SELECT 1, 'MyTenant', 1;
-- ...
CREATE TABLE dbo.Users
(
UserID INT PRIMARY KEY,
Username VARCHAR(320) NOT NULL UNIQUE,
PasswordHash VARBINARY(64), -- because you never store plain text, right?
TenantID INT -- foreign key
--, ...
);
INSERT dbo.Users SELECT 1, 'foo@bar.com', 0x43..., 1;
私たちの場合、新しいテナントを追加したときにデータベースを動的に構築しますが、管理ユーザーがUIで[OK]をクリックしたときではなく、5分ごとに新しいデータベースをキューから取り出し、modelをsingle_userに設定するバックグラウンドジョブがありました、そして各新しいデータベースを順次作成しました。これは、(a)管理者ユーザーがデータベースの作成を待つのを防ぐため、および(b)2人の管理者ユーザーが同時にデータベースを作成しようとしたり、モデルをロックする機能を拒否されたりするのを防ぐために行いました(新しいデータベースの作成時に必要) )。
データベースはTenant000000xx
、xx
表されている名前スキームで作成されましたTenants.TenantID
。これは、代わりに名前付きデータベースのすべての種類有するので、非常に簡単メンテナンスジョブを作ったBurgerKing
、McDonalds
、KFC
その一例としてだけ使用して、我々はファーストフードにあったていないことなどを。
コメントが示唆するように何千ものデータベースを事前に割り当てなかった理由は、管理ユーザーは通常、テナントがどれだけ大きくなるか、優先度が高いかどうかなどをある程度知っていたためです。初期サイズと自動拡張設定、データ/ログファイルの保存先となるディスクサブシステム、リカバリ設定、ヒンジオフするバックアップスケジュール、および使用量を最適に分散するためにデータベースを展開するインスタンスについても決定します(ただし、管理者がこれをオーバーライドできます)。データベースが作成されると、テナントテーブルが選択したインスタンスで更新され、テナントの管理ユーザーが作成され、管理者に新しいテナントに渡す資格情報が電子メールで送信されました。
単一のエントリポイントを使用している場合、複数のテナントに同じユーザー名を持つユーザーを許可することはできません。電子メールアドレスを使用することを選択しました。すべてのユーザーが会社で働いており、企業の電子メールアドレスを使用している場合は問題ありません。ただし、次の2つの理由により、ソリューションは最終的に複雑になりました。
- 複数のクライアントで働くコンサルタントがいて、複数のクライアントにアクセスする必要がありました
- 実際に複数のテナントで構成されるテナントがありました
そのため、TenantUsers
1人のユーザーを複数のテナントに関連付けることができるテーブルができました。
ユーザーが最初にログインすると、アプリは制御データベースの接続文字列のみを認識します。ログインが成功すると、見つかった情報に基づいて接続文字列を作成できます。例えば
SELECT i.Connection
FROM dbo.Instances AS i
INNER JOIN dbo.Tenants AS t
ON i.InstanceID = t.InstanceID
INNER JOIN dbo.TenantUsers AS u
ON i.TenantID = u.TenantID
WHERE u.UserID = @UserID;
これで、アプリはユーザーのデータベースに接続できるようになり(各ユーザーにはデフォルトのテナントがありました)、ユーザーはアクセス可能なテナントから選択できるようになりました。その後、アプリは新しい接続文字列を取得し、そのテナントのホームページにリダイレクトするだけです。
あなたが提案するこの10MMのユーザーエリアに入ると、あなたは間違いなくこれをより良くバランスさせる必要があります。異なる制御データベースに接続する異なるエントリポイントを持つように、アプリケーションを統合することができます。各テナントにサブドメイン(TenantName.YourApplicationDomain.comなど)を付与すると、さらにスケールアウトする必要があるときにそれらを中断することなく、DNS /ルーティングでバックグラウンドでこれを行うことができます。
これにはもっと多くのことがあります-@Darinのように、ここで表面をひっかいているだけです。非無料相談が必要な場合はお知らせください。:-)