web-dev-qa-db-fra.com

Un système multi-locataire avec SQL Server 2016, Shard ou l'isolement du locataire via une base de données distincte par locataire?

Étant donné le cas d'utilisation:

  • Les données des locataires ne doivent pas interférer, un locataire n'a pas besoin des données d'un autre locataire.
  • Chaque locataire peut potentiellement avoir un grand volume de données historiques.
  • SQL Server est hébergé dans une instance AWS EC2.
  • Chaque locataire est géographiquement éloigné.
  • Il est prévu d'utiliser des outils de visualisation tiers tels que PowerBI Embedded
  • Le volume de données devrait augmenter avec le temps
  • Le coût du système est limité.
  • La solution doit être maintenable sans DBA de production 24/7
  • La solution doit pouvoir évoluer horizontalement.
  • Le nombre total de locataires est inférieur à 50

Quelle serait une architecture recommandée, existe-t-il des implémentations de référence pour ce cas d'utilisation? Je pense que de nombreuses personnes ont peut-être déjà rencontré ce problème pour le développement de logiciels d'entreprise.

Je pense que c'est une situation différente de Gestion d'un nombre croissant de locataires dans une architecture de base de données multi-locataires . Le cas d'utilisation mentionné dans cette question concerne un nombre plus élevé de locataires, ce qui est très différent d'avoir très peu (50) de grands locataires. L'architecture mentionnée pourrait être une solution ici, et c'est ce que je veux en savoir plus.

12
D.S.

Le problème avec le partage est que l'application doit savoir quel fragment à interroger. Généralement, cela se fait en partageant quelque chose comme client. Je vais adapter n de mes anciens articles de blog pour l'utiliser comme réponse.

Lorsque vous créez une application pour de nombreux clients, il existe deux façons courantes de concevoir la ou les bases de données:

  • Option A: placer tous les clients dans la même base de données
  • Option 2: créer une base de données par client

Mettre tous les clients dans la même base de données

C'est simple: ajoutez simplement une table Client en haut du schéma, ajoutez une table ClientUsers pour vous assurer que les gens ne voient que leurs propres données, et c'est parti.

Avantages de cette approche:

Gestion plus simple du schéma. Lorsque les développeurs déploient une nouvelle version de l'application, ils n'ont qu'à effectuer des changements de schéma dans une seule base de données. Il n'y a aucun souci à ce que différents clients soient désynchronisés ou sur la mauvaise version.

Optimisation des performances plus facile. Nous pouvons vérifier l'utilisation des index et les statistiques en un seul endroit, implémenter facilement les améliorations et voir les effets immédiatement sur tous nos clients. Avec des centaines ou des milliers de bases de données, même le plus petit changement peut être difficile à coordonner. Nous pouvons vérifier le contenu de notre cache de procédures et savoir avec certitude quelles requêtes ou procédures stockées sont les plus intensives dans l'ensemble de notre application, alors que si nous utilisons des bases de données distinctes par client, nous pouvons avoir plus de difficulté à agréger l'utilisation des requêtes sur différents plans d'exécution.

Plus facile à construire une API externe. Si nous devons accorder l'accès à notre base de données entière aux étrangers pour construire des produits, nous pouvons le faire plus facilement si tous les les données sont dans une seule base de données. Si l'API doit gérer le regroupement des données de plusieurs bases de données sur plusieurs serveurs, elle ajoute du temps de développement et de test. (D'un autre côté, cette chose "plusieurs serveurs" commence à faire allusion à une restriction pour le scénario d'une seule base de données pour les gouverner tous: une base de données signifie généralement que toute notre charge affecte un seul serveur de base de données.) Dans votre cas , avec PowerBI, avoir tout le monde dans une base de données facilitera la gestion des connexions.

Haute disponibilité et reprise après sinistre plus faciles. Il est vraiment très simple de gérer la mise en miroir de bases de données, l'envoi de journaux, la réplication et le clustering si tout ce dont nous avons à nous soucier est une seule base de données. Nous pouvons rapidement construire une sacrée infrastructure.

Mettre chaque client dans sa propre base de données ou éclat

Vous avez toujours besoin d'une liste de clients, mais maintenant cela devient un répertoire - pour chaque client, vous suivez également le fragment dans lequel il vit. Au démarrage, votre application interroge ce tableau et le met en cache dans la RAM. Lorsqu'il a besoin de données pour un client, il se connecte directement à ce fragment (base de données et serveur).

Avantages de cette approche:

Restaurations plus simples pour un seul client. Les clients sont des sacs de viande peu fiables. (Sauf le mien - ce sont des sacs de viande fiables.) Ils ont toutes sortes de moments où ils veulent récupérer toutes leurs données à un moment donné, et c'est une énorme douleur à l'arrière si leurs données sont mélangées avec d'autres données client dans les mêmes tables. Les restaurations dans un scénario de base de données à client unique sont extrêmement simples: il suffit de restaurer la base de données du client. Personne d'autre n'est affecté.

Exportations de données plus faciles. Les clients adorent mettre la main sur leurs données. Ils veulent la sécurité de savoir qu'ils peuvent extraire leurs données à tout moment, en évitant le scénario de verrouillage redouté des fournisseurs, et ils veulent faire leurs propres rapports. Les données de chaque client étant isolées dans leur propre base de données, nous pouvons simplement leur donner une copie de leur propre sauvegarde de base de données. Nous n'avons pas à créer d'API d'exportation de données.

Évolutivité multi-serveurs plus facile. Lorsque notre application a besoin de plus de puissance que ce que nous pouvons obtenir d'un seul serveur, nous pouvons diviser les bases de données entre plusieurs serveurs. Nous pouvons également répartir la charge géographiquement, plaçant les serveurs en Asie ou en Europe pour être plus proches des clients.

Optimisation des performances par client plus facile. Si certains clients utilisent des fonctionnalités ou des rapports différents, nous pouvons créer un ensemble spécialisé d'index ou de vues indexées uniquement pour les clients sans augmenter la taille des données de chacun. Certes, il y a un certain risque ici - en permettant des différences de schéma entre les clients, nous venons de rendre nos déploiements de code un peu plus risqués et notre gestion des performances plus difficile.

Gestion de la sécurité simplifiée. Tant que nous avons correctement verrouillé la sécurité avec un utilisateur par base de données, nous n'avons pas à nous soucier de l'accès du client X au client Les données de Y. Cependant, si nous n'utilisons qu'une seule connexion pour tout le monde, nous n'avons pas vraiment répondu à cette préoccupation.

Fenêtres de maintenance plus faciles. Dans un environnement mondial où les clients sont dispersés à travers le monde, il est plus facile de mettre les clients hors ligne pour la maintenance si nous pouvons le faire en groupe ou zones.

Lequel vous convient le mieux?

Il n’ya pas un seul bon choix: vous devez connaître les forces et les faiblesses de votre entreprise. Prenons deux de mes clients comme exemples.

La société A excelle dans le réglage des performances matérielles. Ils sont vraiment, vraiment bons pour arracher le tout dernier niveau de performances du matériel, et cela ne les dérange pas de remplacer leur matériel SQL Server sur un cycle de 12 à 18 mois. (Ils rafraîchissent les serveurs Web tous les 4 à 6 mois!) Leur talon d'Achille est une exigence de conformité et de sécurité extrême. Ils ont des besoins d'audit incroyables, et il leur est tout simplement plus facile d'implémenter des contrôles pare-balles sur un seul serveur, une seule base de données que de gérer ces exigences sur des milliers de bases de données sur des dizaines de serveurs. Ils ont choisi une base de données, un serveur, de nombreux clients.

La société 2 excelle dans les pratiques de développement. La gestion des modifications de schéma et des déploiements de code sur des milliers de bases de données n'est tout simplement pas un problème pour eux. Ils ont des clients dans le monde entier et traitent les transactions par carte de crédit pour ces clients 24h/24. Ils ont besoin de pouvoir répartir la charge géographiquement et ils ne veulent pas remplacer les serveurs dans le monde tous les 12 à 18 mois. Ils ont choisi une base de données pour chaque client, et cela porte ses fruits alors qu'ils commencent à installer des serveurs SQL en Asie et en Europe pour leurs clients offshore.

16
Brent Ozar

Une autre considération que je n'ai pas encore vue dans d'autres réponses.

Avoir une conception qui permet à de nombreux locataires dans une seule base de données donnera plus tard de la flexibilité. Si des demandes de chargement/évolutivité/sécurité/géolocalisation suggèrent ultérieurement qu'un locataire devrait avoir une base de données distincte, elle peut être créée en restaurant la base de données currect sur la nouvelle instance. Les données des autres locataires sont toujours protégées par les mécanismes en place. Les données désormais obsolètes peuvent être supprimées au fur et à mesure des anciennes et des nouvelles bases de données si le temps le permet.

L'inverse n'est pas vrai. La consolidation de nombreuses bases de données à locataire unique nécessitera beaucoup plus de travail.

5
Michael Green

Une pratique qui rend les modèles multi-locataires beaucoup plus faciles, même si elle rompt la normalisation *, consiste à inclure une colonne sur chaque table pour le locataire. Vous pourriez l'appeler TenantID. De cette façon, chaque requête exécutée sur la base de données peut filtrer sur TenantID sur chaque table, et vous pouvez utiliser le partitionnement de la base de données pour isoler les données de chaque locataire et accélérer les requêtes en ayant des partitions alignées. Il est beaucoup plus facile d'avoir tous les locataires dans une seule base de données de cette façon.

* Cela ne rompt pas toujours la normalisation, mais c'est possible. Par exemple, si vous avez une table Person et PersonAddress. La table Person aura TenantID, PersonID comme clé primaire. La table PersonAddress aura TenantID, PersonID, AddressTypeID comme clé primaire avec ce que je suggère.

Normalement, juste PersonID serait suffisant, car vous pouvez le joindre à nouveau à la table Person pour trouver le Tenant. Je suggère que vous reportiez TenantID à chaque table suivante, même lorsqu'une clé plus fine fonctionnerait.

Je croyais comprendre que le report de toute information dans un tableau qui pouvait être dérivée d'autres données était considéré comme une rupture de la normalisation. Mais peut-être que l'utilisation de touches minces n'est qu'une meilleure pratique.

4
Matthew Sontum