Question

Je travaille sur une application Web située entre un service de courrier électronique et un réseau social. J’estime qu’elle pourrait potentiellement devenir très importante à l’avenir. L’évolutivité me préoccupe donc.

Au lieu d'utiliser une base de données MySQL / InnoDB centralisée et de la partitionner le moment venu, j'ai décidé de créer une base de données SQLite distincte pour chaque utilisateur actif: un utilisateur actif par 'shard'.

De cette manière, sauvegarder la base de données serait aussi simple que de copier le petit fichier de base de données de chaque utilisateur vers un emplacement distant une fois par jour.

La mise à l'échelle sera aussi simple que d'ajouter des disques durs supplémentaires pour stocker les nouveaux fichiers.

Lorsque l'application dépasse un serveur unique, je peux relier les serveurs au niveau du système de fichiers à l'aide de GlusterFS et l'exécuter sans modification, ou configurer un système de proxy SQLite simple qui permet à chaque serveur de manipuler des fichiers SQLite sur des serveurs adjacents.

Les problèmes de simultanéité seront minimes car chaque requête HTTP ne touchera qu'un ou deux fichiers de base de données à la fois, parmi des milliers, et SQLite ne bloquera que les lectures de toute façon.

Je parie que cette approche permettra à mon application d'évoluer avec élégance et de prendre en charge de nombreuses fonctionnalités intéressantes et uniques . Est-ce que je parie mal? Est-ce que je manque quelque chose?

MISE À JOUR : j'ai choisi une solution moins extrême, qui fonctionne bien jusqu'à présent. J'utilise un nombre fixe de fragments - 256 bases de données sqlite, pour être précis. Chaque utilisateur est assigné et lié à un fragment aléatoire par une simple fonction de hachage.

La plupart des fonctionnalités de mon application requièrent un accès à un ou deux fragments uniquement par requête, mais il en existe une en particulier qui nécessite l'exécution d'une requête simple sur 10 à 100 fragments différents sur 256, en fonction de l'utilisateur. Les tests indiquent qu’il faudrait environ 0,02 seconde, voire moins, si toutes les données sont mises en cache dans la RAM. Je pense que je peux vivre avec ça!

UPDATE 2.0 J'ai transféré l'application sur MySQL / InnoDB et j'ai pu obtenir à peu près les mêmes performances pour les demandes régulières, mais pour cette requête nécessitant la marche d'un fragment, innodb est 4-5 fois plus rapide. . Pour cette raison, entre autres, je supprime cette architecture, mais j'espère que quelqu'un l'utilisera quelque part ... merci.

Était-ce utile?

La solution

Si vous devez faire ce que vous appelez "shard marchant", vous risquez de ne pas y parvenir. - qui consiste à rechercher toutes les données d’un groupe d’utilisateurs différents. Ce type particulier de " requête " devra être fait par programme, en interrogeant chacune des bases de données SQLite - et sera très probablement l’aspect le plus lent de votre site. C’est un problème courant dans tous les systèmes où les données ont été " sharded " dans des bases de données séparées.

Si toutes les données sont autonomes pour l'utilisateur, la structure devrait bien évoluer - la clé pour en faire une conception efficace est de savoir comment les données vont probablement être utilisées et si les données d'une personne interagira avec les données d'un autre (dans votre contexte).

Vous devrez peut-être aussi vous méfier des ressources du système de fichiers - SQLite est génial, génial, rapide, etc. - mais vous bénéficiez de certains avantages en termes de mise en cache et d'écriture lorsque vous utilisez une "base de données standard". (c'est-à-dire MySQL, PostgreSQL, etc.) en raison de leur conception. Dans la conception que vous proposez, vous manquerez une partie de cela.

Autres conseils

Cela me semble être un cauchemar d’entretien. Que se passe-t-il lorsque le schéma change sur tous ces DB?

Un problème possible est qu’avoir une base de données pour chaque utilisateur utilisera l’espace disque et la RAM de manière très inefficace, et à mesure que la base d’utilisateurs grandira, l’avantage d’utiliser un moteur de base de données léger et rapide sera complètement perdu.

Une solution possible à ce problème consiste à créer des " minishards ". 1024 bases de données SQLite pouvant héberger jusqu'à 100 utilisateurs chacune . Cela sera plus efficace que l'approche par base de données par utilisateur, car les données sont compressées plus efficacement. Et plus léger que l’approche du serveur de base de données Innodb, car nous utilisons Sqlite.

La concurrence sera également très bonne, mais les requêtes seront moins élégantes (shard_id yuckiness). Qu'en penses-tu?

http://freshmeat.net/projects/sphivedb

SPHiveDB est un serveur pour la base de données sqlite. Il utilise JSON-RPC sur HTTP pour exposer une interface réseau utilisant une base de données SQLite. Il prend en charge la combinaison de plusieurs bases de données SQLite dans un fichier. Il prend également en charge l'utilisation de plusieurs fichiers. Il est conçu pour le schéma de partage extrême - une base de données SQLite par utilisateur.

Si vous créez une base de données distincte pour chaque utilisateur, cela donne l'impression de ne pas établir de relations ... alors pourquoi utiliser une base de données relationnelle?

Je considère cette même architecture car je souhaitais fondamentalement utiliser les bases de données SQLLIte côté serveur comme copie de sauvegarde et de synchronisation pour les clients. Mon idée pour interroger toutes les données est d'utiliser Sphinx pour la recherche en texte intégral et d'exécuter des tâches Hadoop à partir de vidages à plat de toutes les données dans Scribe, puis d'exposer les résultats sous forme de serveurs Web. Ce message me laisse toutefois un peu de temps pour réfléchir. J'espère donc que les gens continueront à répondre avec leur opinion.

Si vos données sont si faciles à partager, pourquoi ne pas utiliser simplement un moteur de base de données standard et si la taille de la base de données est suffisamment grande pour que la base de données devienne le goulet d'étranglement, divisez la base de données avec différents utilisateurs dans différentes instances? L'effet est le même, mais vous n'utilisez pas des dizaines de petites bases de données.

En réalité, vous avez probablement au moins des données partagées qui n'appartiennent à aucun utilisateur, et vous avez probablement souvent besoin d'accéder aux données de plusieurs utilisateurs. Cela posera des problèmes avec l’un ou l’autre système.

Avec une base de données par utilisateur, il serait évidemment très facile de restaurer les données des utilisateurs individuels, mais comme @John dit, les changements de schéma nécessiteraient un peu de travail.

Pas assez pour rendre les choses difficiles, mais assez pour les rendre non triviales.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top