Bewältigung einer wachsenden Anzahl von Mandanten in einer Datenbankarchitektur mit mehreren Mandanten


26

Das Behandeln einer bescheidenen Anzahl von Kunden (Mandanten) auf einem gemeinsamen Server mit separaten Datenbanken für die Anwendungsinstanz jedes Mandanten ist relativ einfach und normalerweise die richtige Methode. Momentan befasse ich mich mit der Architektur einer Anwendung, bei der jeder Mandant eine eigene Datenbankinstanz hat.

Das Problem ist jedoch, dass diese Anwendung eine große Anzahl von Mandanten (5.000 bis 10.000) mit einer beträchtlichen Anzahl von Benutzern hat, möglicherweise 2.000 für einen einzelnen Mandanten. Wir müssen den wöchentlichen Ausbau des Systems durch mehrere Mieter unterstützen.

Zusätzlich wird allen Mietern und ihren Benutzern ein gemeinsamer Anmeldeprozess angezeigt (dh jeder Mieter kann keine eigene URL haben). Dazu benötige ich einen zentralen Anmeldevorgang und ein Mittel, um dem System dynamisch Datenbanken hinzuzufügen und Benutzer zu registrieren.

  • Wie kann der Registrierungs- und Datenbankerstellungsprozess zuverlässig automatisiert werden?

  • Ist es wahrscheinlich, dass das Erstellen und Registrieren von Mandantendatenbanken im System zu Leistungs- oder Sperrproblemen führt. Wenn Sie der Meinung sind, dass dies ein Problem sein könnte, kann jemand einen Lösungsvorschlag unterbreiten?

  • Wie kann ich die zentrale Authentifizierung so verwalten, dass Benutzeranmeldeinformationen mit der Datenbank eines bestimmten Mandanten verknüpft werden, der Benutzer sich jedoch über eine gemeinsame Seite anmelden kann (dh alle über dieselbe Anmelde-URL, aber die Heimanwendung befindet sich in der Datenbank eines bestimmten Mandanten ). Die Mieter müssen in der Lage sein, ihre eigenen Anmeldungen und Berechtigungen zu verwalten, diese müssen jedoch einem zentralen Anmeldesystem bekannt sein. Kann jemand einen Weg vorschlagen, dies zu tun?

  • Wenn ich durch Hinzufügen mehrerer Datenbankserver verkleinern muss, kann jemand Vorschläge machen, mit welchen Problemen ich möglicherweise bei der Verwaltung der Benutzeridentitäten auf verschiedenen Servern (Identitätswechsel usw.) umgehen muss, und wie diese Probleme behoben werden können?


1
Ich musste mich nicht mit einer solchen Situation auseinandersetzen, aber es wäre meine Absicht, das Tenant-Rollout zu bewältigen, indem Server mit so vielen Tenant-Datenbanken vorkonfiguriert werden, wie Sie glauben, dass sie damit umgehen können, und die vorgefertigten Tenant-Datenbanken dann einfach als neue Tenants zugewiesen werden Anmelden. Auf diese Weise müssen Sie sich zumindest beim Bereitstellen von Mandanten-DBs keine Gedanken über Ressourcenkonflikte machen.
Joel Brown

1
Sind Sie sicher, dass Sie 5.000 bis 10.000 Mieter erreichen werden? Und dass alle Ihre Mieter im Bereich von 2.000 Nutzern sein werden? In meinem System war die größte Anzahl von Benutzern unserer Anwendung für einen einzelnen Mieter ungefähr 100. Und von diesen waren nur ungefähr 20 durchgehend aktiv. Kann ich fragen, was die Branche / Anwendung ist?
Aaron Bertrand

@AaronBertrand Es ist ein Learning Management System, bei dem die Dienste teilweise kostenlos und teilweise kostenpflichtig sind.
Coddey

Antworten:


25

Am unteren Ende (500 Mieter / 10000 Nutzer) habe ich es so gemacht. Erstens haben Sie eine "Kontroll" -Datenbank, die global und zentral ist und alle Informationen zu Mandanten und Benutzern enthält (ich glaube wirklich nicht, dass Sie diese als SQL-Authentifizierungsanmeldungen verwalten möchten). Stellen Sie sich eine Datenbank mit dem Namen "Control" mit den folgenden Tabellen vor:

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;

In unserem Fall wurde die Datenbank beim Hinzufügen eines neuen Mandanten dynamisch erstellt, aber nicht, wenn der Administrator auf der Benutzeroberfläche auf OK klickte. Wir hatten einen Hintergrundjob, bei dem alle 5 Minuten neue Datenbanken aus einer Warteschlange gezogen wurden. Setzen Sie model auf single_user und dann jede neue Datenbank seriell erstellt. Wir haben dies getan, um (a) den Administrator daran zu hindern, auf die Erstellung der Datenbank zu warten, und (b) um zu verhindern, dass zwei Administratorbenutzer gleichzeitig versuchen, eine Datenbank zu erstellen, oder auf andere Weise die Möglichkeit verweigert wird, das Modell zu sperren (erforderlich beim Erstellen einer neuen Datenbank) ).

Datenbanken wurden mit dem Namensschema erstellt , Tenant000000xxwo xxdargestellt Tenants.TenantID. Dies machte Wartungsaufträge ganz einfach, statt alle Arten von Datenbanken genannt, die BurgerKing, McDonalds, KFCusw. Nicht , dass wir in Fast - Food waren, nur mit , dass als Beispiel.

Der Grund, warum wir nicht Tausende von Datenbanken im Voraus zugewiesen haben, ist, dass unsere Administratorbenutzer normalerweise eine Vorstellung davon hatten, wie groß der Mandant werden würde, ob sie hohe Priorität hatten usw. Sie hatten also grundlegende Auswahlmöglichkeiten in der Benutzeroberfläche bestimmen die anfängliche Größe und das Autogrowth, auf welches Festplattensubsystem sich die Daten- / Protokolldateien beziehen, welche Wiederherstellungseinstellungen verwendet werden, von welchem ​​Backup-Zeitplan abgehängt wird und welche Instanz die Datenbank bereitgestellt werden soll, um den optimalen Nutzungsausgleich zu erzielen ( obwohl unsere Admins dies außer Kraft setzen könnten). Nachdem die Datenbank erstellt wurde, wurde die Mandantentabelle mit der ausgewählten Instanz aktualisiert, ein Administratorbenutzer für den Mandanten erstellt und unseren Administratoren wurden die Anmeldeinformationen per E-Mail zur Weitergabe an den neuen Mandanten gesendet.

Wenn Sie einen einzelnen Einstiegspunkt verwenden, ist es nicht möglich, dass mehrere Mandanten Benutzer mit demselben Benutzernamen haben. Wir haben uns für die Verwendung der E-Mail-Adresse entschieden. Wenn alle Benutzer für das Unternehmen arbeiten und ihre E-Mail-Adresse für das Unternehmen verwenden, sollte dies in Ordnung sein. Unsere Lösung wurde jedoch aus zwei Gründen komplexer:

  1. Wir hatten Berater, die für mehr als einen unserer Kunden tätig waren und Zugriff auf mehrere benötigten
  2. Wir hatten Mieter, die selbst aus mehreren Mietern bestanden

So haben wir eine TenantUsersTabelle erstellt, mit der ein Benutzer mehreren Mandanten zugeordnet werden konnte.

Wenn sich ein Benutzer anmeldet, kennt die App zunächst nur die Verbindungszeichenfolge für die Steuerungsdatenbank. Wenn eine Anmeldung erfolgreich ist, kann sie anhand der gefundenen Informationen eine Verbindungszeichenfolge erstellen. Z.B

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;

Jetzt konnte die App eine Verbindung zur Datenbank des Benutzers herstellen (jeder Benutzer hatte einen Standardmieter ), oder der Benutzer konnte einen der Mieter auswählen, auf die er zugreifen konnte. Die App ruft dann einfach die neue Verbindungszeichenfolge ab und leitet sie zur Homepage dieses Mandanten weiter.

Wenn Sie in diesen von Ihnen vorgeschlagenen 10-MM-Benutzerbereich gelangen, müssen Sie diesen auf jeden Fall besser ausbalancieren. Möglicherweise möchten Sie die Anwendung so zusammenfassen, dass sie über unterschiedliche Eintrittspunkte verfügt, die eine Verbindung zu verschiedenen Steuerungsdatenbanken herstellen. Wenn Sie jedem Mandanten eine Unterdomäne zuweisen (z. B. Mandantenname.IhreAnwendungsdomäne.com), können Sie dies hinter den Kulissen mit DNS / Routing tun, ohne sie zu unterbrechen, wenn Sie weiter skalieren müssen.

Da steckt noch viel mehr dahinter - wie bei @Darin kratz ich hier nur an der Oberfläche. Lassen Sie mich wissen, wenn Sie eine unverbindliche Beratung benötigen. :-)


Vielen Dank, dass Sie uns Ihre Erfahrungen mitgeteilt haben. Aber du hast Non-free schon geschrieben. :(
Coddey

1
Mein Punkt war, dass ich nur so viel Zeit für kostenlose Beratung habe. :-)
Aaron Bertrand

+1 - ziemlich genau der gleiche Ansatz, den ich zuvor verwendet habe. ~ Die gleiche Anzahl von Mietern hat auch sehr gut funktioniert.
AdaTheDev

Wie gehe ich mit der Beziehung zwischen Master-Datenbank und Mandantendatenbank um? (ohne Verwendung von Triggern usw.)
Jitendra Pancholi

@jitendra nicht wirklich viele Optionen - wie viele Daten haben Sie wirklich in einer Tenant-Datenbank, die sich auf Daten in der Master-Datenbank beziehen muss? Ich bin mir auch nicht sicher, ob ich die populäre Angst vor Auslösern verstehe - ein richtig geschriebener Auslöser ist nichts, vor dem ich Angst haben muss ...
Aaron Bertrand

10

Sie haben selbst ein interessantes Projekt. Ich habe noch nie jemanden direkt gesehen, der versucht hat, etwas so Großes zu implementieren, zumindest auf SQL Server. Je mehr ich Ihren Beitrag lese, desto mehr Fragen kommen auf mich zu ...

Im schlimmsten Fall benötigen Sie in Bezug auf die Infrastruktur (was in geschäftlicher Hinsicht eigentlich das beste Szenario ist) 10.000 Datenbanken und 2.000 Benutzer. Das sind 20.000.000 Benutzer. Sie werden nicht erfolgreich versuchen, 20 M SQL Server-Anmeldungen zu verwalten. IMO. Nur die schiere Anzahl von ihnen, die damit zu tun haben, sie von Server zu Server zu verschieben, auf ID-Kollisionen und nicht übereinstimmende IDs zu achten, und ich bin mir nicht sicher, wie sich SQL Server mit 20 Millionen Zeilen in sys.server_principals verhalten würde. Darüber hinaus möchte Ihre Web-App wahrscheinlich eine Verbindung als einzelner Benutzer oder mit einer sehr geringen Anzahl von Benutzern herstellen. IIS kann Verbindungen nur dann bündeln, wenn die DSN-Zeichenfolgen identisch sind. Eines der Attribute einer DSN-Zeichenfolge ist der Benutzername. Unterschiedliche Benutzer bedeuten kein Pooling.

Sie müssen Ihr eigenes Schema für Benutzeranmeldeinformationen erstellen. Es muss in der Lage sein, herauszufinden, zu welchem ​​Mandanten ein Benutzer gehört, und dann muss Ihr Webcode die richtige Datenbank auswählen. Diese Benutzermetadaten sind kritisch, müssen irgendwo gespeichert werden, müssen geclustert oder gespiegelt werden, müssen schnell sein und müssen gut geschützt werden (aus Sicht der Sicherheit). verschlüssle es.). Unter der Annahme, dass SQL hier sogar eine gute Idee ist, würde ich diese Datenbank von den Instanzen fernhalten, die Server-Mandanten verwenden. Dies ist sicherheits- und lastseitig hilfreich, obwohl ich vermute, dass nach der Validierung eines Benutzers und der Steuerung der Webanwendung in die richtige Datenbank auf einer anderen Instanz keine diesbezüglichen Benutzer-Metadaten mehr abgefragt werden Benutzer.

Kurze Frage: Sollen zwei verschiedene Benutzer, die zu zwei verschiedenen Mandanten gehören, denselben Benutzernamen haben dürfen?

Noch eine kurze Frage: Wenn ich Ihnen sage, dass ich für FuBar, Inc. arbeite, woher wissen Sie das? Wird FuBar Ihnen eine Liste der Benutzer geben und Sie geben ihnen eine Liste der Benutzernamen zurück, oder werden sie sich selbst versorgen?

Sie müssen mehrere Instanzen verwenden. Wenn sich sogar ein Bruchteil dieser Benutzer dazu entscheidet, auf einmal auf die Anwendung zuzugreifen, schmilzt eine einzelne Instanz. Es sind nicht genügend Worker-Threads vorhanden, um alle diese Anforderungen gleichzeitig auszuführen. Wenn nur 1000 Benutzer gleichzeitig auf Ihre Instanz zugreifen, werden wahrscheinlich keine Worker-Threads mehr vorhanden sein und die Anforderung wird gestapelt und abgewartet. Ich habe gesehen, wie das passiert ist. Das unmittelbare Symptom ist, dass sich neue Verbindungen nicht bei der Instanz anmelden können, da keine Worker-Threads für deren Wartung verfügbar sind. Wenn dies ein sehr kurzlebiges Verhalten ist, kann Ihre App überleben. Wenn nicht oder Ihre App pingelig ist, erhalten Benutzer Fehler.

Auch wenn Sie nicht viele Mieter haben, sollten Sie sich Gedanken über die Zukunft und die Automatisierung machen, denn wenn Sie feststellen, dass Ihr Server überlastet ist und 10 neue Mieter online gehen können, ist es viel zu spät und Ihr Service (und Ihre Kunden und Ihre zukünftigen Ex-Kunden werden leiden, bis Sie das Problem gelöst haben.

Sie benötigen eine Möglichkeit, Datenbanken von überlasteten Servern auf leicht ausgelastete (oder neue) Server zu verschieben. Ob Sie ein Ausfallfenster erhalten, hängt von Ihrem SLA ab.

Stellen Sie eine bestimmte Anwendung wie SalesForce bereit oder sind diese Datenbanken nur Container für das, was Ihre Mandanten einfügen möchten?

Wie groß sind die Datenbanken? Wenn sie nicht sehr groß sind, können Sie sie einfach aus einer Sicherungsdatei wiederherstellen, die eine Vorlage enthält. (Das ist nicht viel anders als das, was die Modelldatenbank tut, aber ich habe seit meinen Tagen mit SQL 6.5 niemanden mehr gesehen, der das Modell wirklich gut verwendet.) Nachdem die Vorlage unter dem neuen Datenbanknamen wiederhergestellt wurde, können Sie dies tun Passen Sie dann die neue Datenbank nach Bedarf für einen bestimmten Mandanten an. Sie können die Anpassung natürlich erst vornehmen, wenn Sie den Mieter haben. Wenn die Datenbank groß ist, befolgen Sie möglicherweise die gleichen grundlegenden Schritte, mit der Ausnahme, dass Sie die Wiederherstellung im Voraus durchführen, bevor ein neuer Mandant den Speicherplatz benötigt. Sie können ein paar dieser Datenbanken behalten, vielleicht eine pro Instanz. Wenn Sie zu viele behalten, werden Sie möglicherweise gezwungen, mehr Hardware und / oder Speicher zu kaufen, als Sie benötigen.

Wie gehen Sie mit Aktualisierungen der Schemas um, wenn es sich um Ihre eigene App handelt? Wie können Sie Versionen der Datenbank direkt mit Versionen des Codes verbinden, wenn Sie eine einzelne URL verwenden, die zu Ihrer Web-App führt?

Wie erkennt und zerstört man nicht mehr genutzte Datenbanken? Warten Sie, bis Ihre A / R-Gruppe sagt, dass jemand seine Rechnung seit drei Monaten nicht bezahlt hat?

Wenn Mandanten Berechtigungen verwalten, bedeutet dies, dass sie etwas über die Funktionsweise der App wissen oder dass Ihre App eine sehr einfache Rollenstruktur aufweist. Am Beispiel von Blogger können Benutzer (Beiträge lesen), (Beiträge lesen und Kommentare abgeben), (... und Beiträge erstellen), (... und die Beiträge anderer bearbeiten), (... und zurücksetzen Passwörter anderer Benutzer) oder (... und was auch immer). Es sollte nicht allzu schwierig sein, eine Rolle für die verschiedenen Rechte zu haben und einen Benutzer der einen oder anderen Rolle zuzuweisen, aber Sie möchten nicht, dass Ihre App GRANT-Anweisungen ausführt. Achten Sie auf Rollen, die eine Hierarchie haben und von der Vererbung abhängen. Dies kann verwirrend werden. Wenn Sie einen Benutzer heraufstufen oder herabstufen, würde ich sagen, dass Sie ihn aus allen zugeordneten Rollen entfernen und ihn dann wieder zu der einen Rolle hinzufügen, die er benötigt. Oh,

Ich denke, dass ich hier nur die Oberfläche zerkratzt habe, und dieser Beitrag ist schon zu lang. Was Sie wirklich brauchen, ist ein Buch oder zumindest ein Whitepaper von jemandem, der dies getan hat. Die meisten dieser Jungs werden nicht reden, wenn sie es als Wettbewerbsvorteil ansehen.


Vielen Dank für die Kommentare. Tatsächlich ist das Projekt interessant. Aufgrund der Wortbegrenzung halte ich den Kommentar sehr präzise. Es ist ein Learning Management System, bei dem jeder Mieter ungefähr 120-150 Tische haben wird. Kein Benutzer hat den gleichen Benutzernamen, unabhängig vom Mieter. Um die Komplexität weiter zu verringern, wird die DNS-CNAME-Zuordnung verwendet (Beispiel tenant1.abc.com). Jetzt ist der Siedepunkt - es in der richtigen Weise zu entwerfen, so dass es allen Vorschlägen gerecht wird, die Sie geteilt haben, und ich mache mir Sorgen um. Whitepaper zu bekommen ist lobenswert, aber vielleicht nicht einfach. Wenn Sie können, sollten Sie mehr Input suchen. !!!!
Coddey
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.