6.1 Bataille d'abréviations : BASE vs. ACIDE
« En chimie, le pH mesure l'acidité relative d'une solution aqueuse. L'échelle de pH va de 0 (substances fortement acides) à 14 (substances fortement alcalines) ; l'eau pure à 25°C a un pH de 7 et est neutre. Les ingénieurs de données ont utilisé cette métaphore pour comparer les bases de données concernant la fiabilité des transactions." Probablement, l'idée était la suivante : plus le pH est élevé, c'est-à-dire plus la base de données est proche de "alcaline" ("BASE"), moins les transactions sont fiables. |
Les bases de données relationnelles populaires, telles que MySQL, sont apparues uniquement sur la base d'ACID. Mais depuis une dizaine d'années, les bases de données dites NoSQL, qui regroupent plusieurs types de bases de données très différents sous ce nom, se sont plutôt bien passées d'ACID. En fait, il existe un grand nombre de développeurs qui travaillent avec des bases de données NoSQL et ne se soucient pas du tout des transactions et de leur fiabilité. Voyons s'ils ont raison.
Vous ne pouvez pas parler en général de la base de données NoSQL, car c'est juste une bonne abstraction. Les bases de données NoSQL diffèrent les unes des autres dans la conception des sous-systèmes de stockage de données, et même dans les modèles de données : NoSQL est à la fois CouchDB orienté document et graphe Neo4J. Mais si nous en parlons dans le contexte des transactions, ils ont tous tendance à être similaires en une chose : ils fournissent des versions limitées d'atomicité et d'isolation, et ne fournissent donc pas de garanties ACID. Pour comprendre ce que cela veut dire, répondons à la question : que proposent-ils, sinon ACID ? Rien?
Pas vraiment. Après tout, comme les bases de données relationnelles, elles doivent également se vendre dans un bel emballage. Et ils ont trouvé leur propre abréviation "chimique" - BASE.
6.2 BASE comme antagoniste
Et là encore, je n'irai pas dans l'ordre des lettres, mais je commencerai par le terme fondamental - la cohérence. Je vais devoir niveler votre effet de reconnaissance, car cette cohérence n'a pas grand-chose à voir avec la cohérence d'ACID. Le problème avec le terme cohérence est qu'il est utilisé dans trop de contextes. Mais cette cohérence a un contexte d'utilisation beaucoup plus large, et en effet c'est exactement la cohérence dont il est question lorsque l'on parle de systèmes distribués.
Les bases de données relationnelles dont nous avons parlé ci-dessus fournissent différents niveaux d'isolation des transactions, et les plus strictes d'entre elles garantissent qu'une transaction ne peut pas voir les modifications non valides apportées par une autre transaction. Si vous vous trouvez à la caisse d'un magasin et qu'à ce moment-là, l'argent du loyer est retiré de votre compte, mais que la transaction avec le transfert d'argent pour le loyer échoue et que votre compte revient à sa valeur précédente (l'argent est non débitée), alors votre transaction de paiement à la caisse ne remarquera pas ces gestes de tout le monde - après tout, cette transaction n'a jamais été effectuée, et sur la base de l'exigence d'isolement de la transaction, ses modifications temporaires ne peuvent pas être remarquées par d'autres transactions.
De nombreuses bases de données NoSQL renoncent à la garantie d'isolement et offrent une "cohérence éventuelle" grâce à laquelle vous verrez éventuellement des données valides, mais il est possible que votre transaction lise des valeurs non valides, c'est-à-dire temporaires, partiellement mises à jour ou obsolètes. Il est possible que les données deviennent cohérentes en mode "paresseux" lors de la lecture ("paresseux au moment de la lecture").
NoSQL a été conçu comme une base de données pour l'analyse en temps réel, et pour atteindre une plus grande vitesse, ils ont sacrifié la cohérence. Et Eric Brewer, le même gars qui a inventé le terme BASE, a formulé le soi-disant "théorème CAP", selon lequel :
Pour toute implémentation du calcul distribué, il est possible de fournir au maximum deux des trois propriétés suivantes :
- cohérence des données ( cohérence ) - les données sur différents nœuds (instances) ne se contredisent pas ;
- disponibilité ( disponibilité ) - toute demande adressée à un système distribué se termine par une réponse correcte, mais sans garantie que les réponses de tous les nœuds du système sont les mêmes;
- tolérance de partition (tolérance de partition ) - Même s'il n'y a pas de connexion entre les nœuds, ils continuent à fonctionner indépendamment les uns des autres.
Si vous voulez une explication très simple de CAP, alors c'est parti.
Il y a des opinions selon lesquelles le théorème CAP ne fonctionne pas et est généralement formulé de manière trop abstraite. D'une manière ou d'une autre, les bases de données NoSQL refusent souvent la cohérence dans le cadre du théorème CAP, qui décrit la situation suivante : les données ont été mises à jour dans un cluster avec plusieurs instances, mais les changements n'ont pas encore été synchronisés sur toutes les instances. Rappelez-vous, j'ai mentionné l'exemple DynamoDB ci-dessus, qui m'a dit : vos modifications sont devenues durables - voici un HTTP 200 pour vous - mais je n'ai vu les modifications qu'après 10 secondes ? Un autre exemple de la vie quotidienne d'un développeur est le DNS, le système de noms de domaine. Si quelqu'un ne le sait pas, alors c'est exactement le "dictionnaire" qui traduit les adresses http (s) en adresses IP.
L'enregistrement DNS mis à jour est propagé aux serveurs en fonction des paramètres d'intervalle de mise en cache - les mises à jour ne sont donc pas immédiatement perceptibles. Eh bien, une incohérence temporelle similaire (c'est-à-dire une cohérence éventuelle) peut arriver à un cluster de bases de données relationnelles (par exemple, MySQL) - après tout, cette cohérence n'a rien à voir avec la cohérence d'ACID. Par conséquent, il est important de comprendre qu'en ce sens, les bases de données SQL et NoSQL ne seront probablement pas très différentes lorsqu'il s'agit de plusieurs instances dans un cluster.
De plus, la cohérence de bout en bout peut signifier que les demandes d'écriture seront faites dans le désordre : c'est-à-dire que toutes les données seront écrites, mais la valeur qui sera éventuellement reçue ne sera pas la dernière dans la file d'attente d'écriture. .
Les bases de données NoSQL non-ACID ont un soi-disant « état souple » en raison du modèle de cohérence de bout en bout, ce qui signifie que l'état du système peut changer au fil du temps, même sans entrée. Mais ces systèmes s'efforcent d'offrir une plus grande accessibilité. Fournir une disponibilité à 100 % n'est pas une tâche anodine, nous parlons donc de "disponibilité de base". Et ensemble ces trois notions : « basicly available », « soft state » (« soft state ») et « eventual consistance » forment l'acronyme BASE.
Pour être honnête, le concept de BASE me semble être un emballage marketing plus vide que ACID - car il n'apporte rien de nouveau et ne caractérise en rien la base de données. Et attacher des étiquettes (ACID, BASE, CAP) à certaines bases de données ne peut que dérouter les développeurs. J'ai quand même décidé de vous présenter ce terme, car il est difficile de le contourner lors de l'étude de la base de données, mais maintenant que vous savez de quoi il s'agit, je souhaite que vous l'oubliiez au plus vite. Et revenons au concept d'isolement.
6.3 Donc les bases de données BASE ne répondent pas du tout aux critères ACID ?
Essentiellement, là où les bases de données ACID diffèrent des non-ACID, c'est que les non-ACID renoncent en fait à l'isolement. C'est important à comprendre. Mais il est encore plus important de lire la documentation de la base de données et de la tester comme le font les gars du projet Hermitage. Peu importe comment exactement les créateurs de telle ou telle base de données appellent leur idée - ACID ou BASE, CAP ou non CAP. L'important est ce que fournit exactement telle ou telle base de données.
Si les créateurs de la base de données prétendent qu'elle fournit des garanties ACID, il y a probablement une raison à cela, mais il est conseillé de la tester vous-même pour comprendre si c'est le cas et dans quelle mesure. S'ils déclarent que leur base de données ne fournit pas de telles garanties, cela peut signifier les choses suivantes :
-
Le DB ne fournit aucune garantie d'atomicité. Alors que certaines bases de données NoSQL offrent une API distincte pour les opérations atomiques (par exemple DynamoDB) ;
- La base de données ne fournit aucune garantie d'isolement. Cela peut signifier, par exemple, que la base de données n'écrira pas les données dans l'ordre dans lequel elles ont été écrites.
Quant à la garantie de durabilité, de nombreuses bases de données font des compromis sur ce point dans un souci de performance. L'écriture sur disque est une opération trop longue, et il existe plusieurs façons de résoudre ce problème. Je ne veux pas trop entrer dans la théorie des bases de données, mais pour que vous compreniez à peu près dans quelle direction regarder, je décrirai en termes généraux comment différentes bases de données résolvent le problème de durabilité.
Pour comparer différentes bases de données, entre autres choses, vous devez savoir quelles structures de données sous-tendent le sous-système de stockage et de récupération de données d'une base de données particulière. En bref : différentes bases de données ont différentes implémentations de l'indexation, c'est-à-dire l'organisation de l'accès aux données. Certains d'entre eux vous permettent d'écrire des données plus rapidement, d'autres - de les lire plus rapidement. Mais on ne peut pas dire en général que certaines structures de données augmentent ou diminuent la durabilité.
6.4 comment les différentes bases de données indexent les données, et comment cela affecte la durabilité, et plus encore
Il existe deux approches principales pour stocker et récupérer des données.
Le moyen le plus simple d'enregistrer des données consiste à ajouter des opérations à la fin du fichier de manière similaire à un journal (c'est-à-dire qu'une opération d'ajout se produit toujours) : peu importe si nous voulons ajouter, modifier ou supprimer des données - tout Les opérations CRUD sont simplement écrites dans le journal. La recherche dans le journal est inefficace, et c'est là que l'index entre en jeu - une structure de données spéciale qui stocke des métadonnées sur l'endroit exact où les données sont stockées. La stratégie d'indexation la plus simple pour les journaux est une carte de hachage qui assure le suivi des clés et des valeurs. Les valeurs seront des références au décalage d'octet pour les données écrites à l'intérieur du fichier, qui est le journal (log) et est stocké sur le disque. Cette structure de données est entièrement stockée en mémoire, tandis que les données elles-mêmes sont sur disque, et s'appelle une arborescence LSM (Log Structured Merge).
Vous vous êtes probablement demandé : si nous écrivons tout le temps nos opérations dans le journal, celui-ci augmentera de manière exorbitante ? Oui, et donc la technique de compactage a été inventée, qui "nettoie" les données avec une certaine périodicité, à savoir, ne laisse que la valeur la plus pertinente pour chaque clé, ou la supprime. Et si nous avons plus d'un journal sur disque, mais plusieurs, et qu'ils sont tous triés, alors nous obtiendrons une nouvelle structure de données appelée SSTable ("table de chaînes triées"), ce qui améliorera sans aucun doute nos performances. Si nous voulons trier en mémoire, nous obtiendrons une structure similaire - la soi-disant MemTable, mais avec elle le problème est que si un crash fatal de la base de données se produit, alors les données écrites en dernier (situées dans MemTable, mais pas encore écrites dans disque) sont perdus. En fait,
Une autre approche de l'indexation est basée sur les B-trees (« B-trees »). Dans un arbre B, les données sont écrites sur le disque dans des pages de taille fixe. Ces blocs de données ont souvent une taille d'environ 4 Ko et ont des paires clé-valeur triées par clé. Un nœud B-tree est comme un tableau avec des liens vers une plage de pages. Max. le nombre de liens dans un tableau est appelé le facteur de branchement. Chaque plage de pages est un autre nœud B-tree avec des liens vers d'autres plages de pages.
Finalement, au niveau de la feuille, vous trouverez des pages individuelles. Cette idée est similaire aux pointeurs dans les langages de programmation de bas niveau, sauf que ces références de page sont stockées sur disque plutôt qu'en mémoire. Lorsque des INSERT et des DELETE se produisent dans la base de données, certains nœuds peuvent se diviser en deux sous-arbres pour correspondre au facteur de branchement. Si la base de données échoue pour une raison quelconque au milieu du processus, l'intégrité des données peut être compromise. Pour éviter que cela ne se produise, les bases de données utilisant des arbres B maintiennent un "journal d'écriture anticipée", ou WAL, dans lequel chaque transaction est enregistrée. Ce WAL est utilisé pour restaurer l'état du B-tree s'il est corrompu. Et il semble que c'est ce qui rend les bases de données utilisant les B-trees meilleures en termes de durabilité. Mais les bases de données basées sur LSM peuvent également maintenir un fichier qui remplit essentiellement la même fonction que WAL. Je vais donc répéter ce que j'ai déjà dit, et peut-être plus d'une fois : comprendre les mécanismes de fonctionnement de la base de données que vous avez choisie.
Ce qui est certain avec les arbres B, cependant, c'est qu'ils sont bons pour la transactionnalité : chaque clé n'apparaît qu'à un seul endroit dans l'index, tandis que les sous-systèmes de stockage journalisés peuvent avoir plusieurs copies de la même clé dans différents fragments (par exemple, jusqu'à ce que le prochain compactage est effectué).
Cependant, la conception de l'index affecte directement les performances de la base de données. Avec une arborescence LSM, les écritures sur le disque sont séquentielles et les arbres B provoquent plusieurs accès aléatoires au disque. Les opérations d'écriture sont donc plus rapides avec LSM qu'avec les arbres B. La différence est particulièrement importante pour les disques durs magnétiques (HDD), où les écritures séquentielles sont beaucoup plus rapides que les écritures aléatoires. La lecture est plus lente sur les arborescences LSM car vous devez parcourir plusieurs structures de données et tables SS différentes qui sont à différents stades de compactage. Plus en détail, cela ressemble à ceci. Si nous faisons une simple requête de base de données avec LSM, nous chercherons d'abord la clé dans le MemTable. Si ce n'est pas là, nous regardons la SSTable la plus récente ; sinon, nous regardons l'avant-dernière SSTable, et ainsi de suite. Si la clé demandée n'existe pas, alors avec LSM nous le saurons en dernier. Les arbres LSM sont utilisés, par exemple, dans : LevelDB, RocksDB, Cassandra et HBase.
Je décris tout cela de manière si détaillée que vous comprenez que lors du choix d'une base de données, vous devez prendre en compte de nombreux éléments différents : par exemple, prévoyez-vous d'écrire ou de lire davantage de données ? Et je n'ai pas encore mentionné la différence entre les modèles de données (avez-vous besoin de parcourir les données, comme le permet le modèle de graphe ? Existe-t-il des relations entre différentes unités dans vos données - alors les bases de données relationnelles viendront à la rescousse ?), et 2 types de schémas de données - lors de l'écriture (comme dans de nombreux NoSQL) et de la lecture (comme dans le relationnel).
Si l'on revient sur l'aspect de la pérennité, alors la conclusion sera la suivante : toute base de données qui écrit sur disque, quels que soient les mécanismes d'indexation, peut apporter de bonnes garanties sur la pérennité de vos données, mais il faut traiter avec chaque base de données spécifique , ce qu'il offre exactement.
6.5 Fonctionnement des bases de données en mémoire
Soit dit en passant, en plus des bases de données qui écrivent sur disque, il existe également des bases de données dites "en mémoire" qui fonctionnent principalement avec de la RAM. En bref, les bases de données en mémoire offrent généralement une durabilité inférieure pour des vitesses d'écriture et de lecture plus rapides, mais cela peut être approprié pour certaines applications.
Le fait est que la mémoire RAM a longtemps été plus chère que les disques, mais récemment, elle a commencé à devenir rapidement moins chère, ce qui a donné naissance à un nouveau type de base de données - ce qui est logique compte tenu de la vitesse de lecture et d'écriture des données de la RAM. Mais vous demanderez à juste titre : qu'en est-il de la sécurité des données de ces bases de données ? Là encore, vous devez regarder les détails de la mise en œuvre. En général, les développeurs de telles bases de données proposent les mécanismes suivants :
- Vous pouvez utiliser la RAM alimentée par des piles ;
- Il est possible d'écrire des journaux de modifications sur le disque (quelque chose comme les WAL mentionnés ci-dessus), mais pas les données elles-mêmes ;
- Vous pouvez périodiquement écrire des copies de l'état de la base de données sur le disque (ce qui, sans utiliser d'autres options, ne donne aucune garantie, mais améliore seulement la durabilité) ;
- Vous pouvez répliquer l'état de la RAM sur d'autres machines.
Par exemple, la base de données Redis en mémoire, qui est principalement utilisée comme file d'attente de messages ou cache, manque de durabilité d'ACID : elle ne garantit pas qu'une commande exécutée avec succès sera stockée sur le disque, car Redis vide les données sur le disque (si vous ont la persistance activée) uniquement de manière asynchrone, à intervalles réguliers.
Cependant, ce n'est pas critique pour toutes les applications : j'ai trouvé un exemple de l'éditeur en ligne coopératif EtherPad, qui vidait toutes les 1 à 2 secondes, et potentiellement l'utilisateur pouvait perdre quelques lettres ou un mot, ce qui n'était guère critique. Sinon, puisque les bases de données en mémoire sont bonnes dans la mesure où elles fournissent des modèles de données qui seraient difficiles à implémenter avec des index de disque, Redis peut être utilisé pour implémenter des transactions - sa file d'attente prioritaire vous permet de le faire.
GO TO FULL VERSION