Mais recommençons.
En 2010, j'ai travaillé chez Google Wave, où nous avons essayé de créer des espaces collaboratifs modifiables pour remplacer les e-mails, Google Docks, les forums, les messages instantanés et de nombreuses autres applications à tâche unique. Parmi mes outils, j'aime particulièrement l'environnement généraliste, nulle part ailleurs comme dans Wave non formulé à ce moment là des fonctionnalités. Contrairement à la plupart des autres outils, l'environnement polyvalent n'impose pas son propre flux de travail, vous pouvez donc l'utiliser pour planifier des vacances, créer des wikis, jouer à des jeux de société avec des amis, planifier des réunions de travail et bien plus encore.
En interne, la coédition de Wave fonctionne au-dessus d'une transformation opérationnelle (OT), et existe depuis des jours à cette époque: notre algorithme était basé sur une discussion de Jupiter en 1995. Pour chaque document, l'algorithme conserve une liste chronologique distincte des changements, «Type H à la position 0», «Type i à la position 1», etc. Dans la plupart des cas, les utilisateurs modifient la dernière version du document et le journal ressemble à une séquence de modifications, cependant, lors de la co-création, nous sommes confrontés à des modifications simultanées.
Dans ce cas, la première modification qui parvient au serveur est enregistrée comme d'habitude et la suivante, si elle s'avère obsolète, est comparée au journal des événements pour déterminer les objectifs initiaux de l'utilisateur. (Plus souvent qu'autrement, tout se résume à la mise à jour des positions des symboles.) Ensuite, l'algorithme, supposément "c'est le résultat souhaité par l'utilisateur", ajoute une nouvelle opération, comme git-rebase en temps réel.
Avec la fermeture de Google Wave, j'ai porté le modèle OT sur ShareJS . À l'époque, node me semblait nouveau et étrange, et si je me souviens bien, j'ai lancé ShareJS avant même la sortie de npm. Un simple co-éditeur ne nécessitait que mille lignes de code, et dans la démo j'ai co-édité le document dans le navigateur et dans l'application.
À la base, OT est une boucle for () embellieavec plusieurs fonctions d'aide pour mettre à jour le décalage des caractères. En pratique, OT est simple, facile à comprendre, rapidement mis en service et fonctionne très bien. (10 à 100 000 opérations par seconde en javascript non optimisé, 1 à 20 millions en C optimisé ). Le journal des événements peut consommer plus de mémoire que d'habitude, mais il peut être réduit si vous le souhaitez, bien qu'il ne fonctionnera pas pour combiner en particulier les anciennes modifications. L'attribution globale des opérations nécessitera un serveur centralisé, mais la plupart des systèmes ont déjà un tel serveur ou une telle base de données, n'est-ce pas?
Serveurs centralisés
Un problème OT important est sa dépendance à un serveur centralisé. Vous êtes-vous déjà demandé pourquoi, en autorisant l'accès à un document Google Docs via les réseaux sociaux, vous étiez confronté à un message étrange du type "Ce document est surchargé et son édition est désactivée"? La raison (à mon avis) est la suivante: lorsque vous ouvrez un document, un serveur spécifique est sélectionné pour traiter toutes ses modifications, et quand une foule d'utilisateurs se jette sur le document, le système doit s'efforcer de ne pas surcharger le serveur.
Il existe plusieurs façons de contourner ce problème: en plus du partitionnement des sous-documents (comme dans Google Docks), vous pouvez apporter des modifications via une boucle de relance, en contournant les transactions de la base de données, afin que le problème de sérialisation soit pris en charge par la même base de données (c'est ainsi que Firepad fonctionneet ShareDB ).
Cependant, OT n'est pas parfait. Nous voulions remplacer le courrier électronique par Wave, mais le courrier prend en charge la fusion, une chaîne de lettres peut s'étendre à de nombreuses entreprises et tout fonctionne avec succès. De plus, contrairement aux messages Facebook, les e-mails peuvent être envoyés aux entreprises mentionnées dans la colonne «copie». Si nous voulons que Wave remplace le courrier, il aura également besoin de la fonctionnalité d'envoi de messages sans accès au réseau externe, par exemple, lorsque j'envoie une lettre à mon collègue à la table suivante. Mais comment pouvez-vous mettre en œuvre tout cela en plus de OT? Nous avons réussi à mettre en place un tel processus, mais il s'est avéré trop complexe et plein d'erreurs: nous avons créé un diagramme, dans lequel chaque protocole wave a mis en place une arborescence de serveurs wave pour transférer les opérations dans les deux sens, mais cela n'a jamais complètement fonctionné. Il y a un peu moins de dix ans, au Wave Protocol Summit, j'ai fait une présentation sur la façon de créer et de configurer un tel réseau, mais malgré toute ma préparation et tous les contrôles préliminaires, le strict respect de chaque étape de la présentation elle-même a échoué, et le réseau n'a jamais fonctionné. Je ne sais toujours pas pourquoi cela s'est produit, mais quels que soient les bogues, ils n'ont pratiquement jamais été corrigés dans la version publique, c'était trop difficile.
Décollage CRTD
Comme je l'ai déjà mentionné, l'algorithme principal Wave a été créé il y a assez longtemps, en 1995, et je ne me souviens même pas d'avoir Internet à la maison à ce moment-là. Depuis lors, les chercheurs ont travaillé sans relâche pour améliorer les performances de l'OT, et dans la direction la plus prometteuse, ils utilisent CRTD (Conflict-Free Replicated data types). Cette approche est quelque peu différente de l'habituelle et vous permet d'éditer des fichiers en temps réel sans avoir besoin d'un serveur central. La présentation de Martin décrit leur travail mieux que je ne pourrais les décrire, alors je vais sauter les détails.
Les gens me demandent mon avis sur la CRTD depuis des années, et ma réponse ressemble toujours à ceci:
Ils sont soignés et je suis heureux que les gens travaillent dessus, cependant:
- . . , 100 Delta-CRTD . (: B4.)
- - CRTD , , 100 automerge master 83 . , , , , . ( automerge 1.1 .)
- Pendant des années, la fonctionnalité présente dans OT a été absente dans CRDT, par exemple, personne n'a encore fait de CRDT avec le support de / object move / (transférer quelque chose d'une partie de l'arborescence JSON à une autre). De telles procédures sont nécessaires pour des applications telles que Workflowy, et OT fait un excellent travail avec elles .
- Les CRDT sont complexes en eux-mêmes et difficiles à raisonner.
- Vous avez probablement déjà un serveur / une base de données centralisé.
Malgré toutes mes critiques, j'ai ignoré le CRDT, mais ce faisant, ignoré la littérature pertinente, et à ma grande surprise, j'ai raté l'amélioration silencieuse et imperceptible du CRDT. Dans sa présentation (qui mérite plus que votre attention), Martin aborde les principaux points:
- : CRDT (Automerge / RGA Y.js / YATA) [log(n)] . ( .)
- : - , 54- . automerge , Y.js, Y.js 100 160 3 . .
- : , .
- : , CRDT OT. , automerge .
Le raisonnement pour la vitesse ne m'a pas convaincu, donc pour tester l'idée, j'ai indépendamment implémenté et testé CRDT dans Rust via un B-tree en utilisant des idées d'automerge. Il manquait de fonctionnalités (suppression de caractères, conflits), mais il était capable de traiter 6 millions de modifications par seconde . (Chaque itération a apporté 2000 modifications à un document vierge par deux utilisateurs alternés, ce qui a pris 330 microsecondes au total, soit 6,06 millions de modifications par seconde.) Les CRDT se sont donc vraiment améliorés et la différence de vitesse entre eux et OT est maintenant encore moindre qu'entre Rust et Javascript.
Tous ces correctifs se trouvent depuis longtemps dans la section "Prochainement" de la branche des performances d'automerge, mais après tout, l'automerge n'est pas le seul CRDT. Y.js fait ses preuves et contourne facilement la version actuelle d'automerge dans ses tests . Il manque la fonctionnalité qui m'intéresse, mais en général, il est certainement plus facile de corriger l'implémentation existante que de créer un nouvel algorithme.
Inventer le futur
Je suis très soucieux de faire des progrès. Qu'est-ce que ce serait étrange de ne pas avoir en usage dans cent ans? Évidemment, nous aurons un montage en temps réel, mais je ne suis plus sûr de sa mise en œuvre via OT et de tout le travail que j'ai fait à cet égard, ce qui ne peut que m'attrister.
JSON et REST sont omniprésents de nos jours. Disons que dans 15 ans, la coédition en temps réel sera également omniprésente. Quel serait l'homologue JSON en termes de co-création pour un transfert facile vers votre projet? Dans cet avenir glorieux, nous aurons besoin d'une implémentation de haute qualité de CRDT, car pour certaines applications, OT ne fonctionnera tout simplement pas, créer une version en temps réel de GIt à travers lui, ou une simple variation de Google Wave ne fonctionnera plus. Mais si nous avons déjà une bonne implémentation CRDT, avons-nous également besoin d'une implémentation OT? Je ne pense pas, car il ne sera pas difficile de transférer toutes les fonctionnalités d'OT vers CRDT (y compris, d'ailleurs, les opérations de coupe), alors que l'inverse n'est pas vrai. Les gens intelligents ne sont pas d'accord avec moi, mais à mon avis, étant donné que nous avons un bon CRDT rapide pour chaque langue,le besoin d'ergothérapie disparaîtra complètement.
L'un des avantages de l'OT est qu'il peut être facilement implémenté dans des systèmes centralisés - comme la plupart des applications modernes - mais les algorithmes distribués sont tout aussi bien implémentés. (Jetez un œil à Github par exemple.) À mon avis, un CRDT de haute qualité sur wasm est plus rapide qu'une implémentation OT dans JS. Et si vous n'êtes concerné que par les systèmes centralisés, rappelez-vous: les restrictions OT ont conduit Google à des problèmes de dimensionnement dans Google Docs.
Il me semble donc que le moment est venu de passer à un petit CRDT rapide. Pour la plupart, le travail académique a déjà été fait, la question reste pour les implémentations réussies.
Et après
Je suis de moins en moins concerné par le monde des applications centralisées. Les applications interagissent avec mes données, sur mes appareils, et il serait grand temps que ces applications réagissent en conséquence à de telles connexions. Je veux que mon ordinateur portable et mon téléphone puissent se transférer des données via wifi, et non en téléchargeant mes données sur des serveurs dans un autre pays. Surtout si ces serveurs sont financés par des géants de la publicité qui se disputent mon attention .
Philosophiquement, lorsque je modifie un document dans Google Docs, mon ordinateur demande à Google l' autorisation de modifier le fichier (car si pour une raison quelconque le serveur dit non, je perds toutes mes modifications). A titre de comparaison, quand
git push
dans github, je viens de notifiergithub à propos des modifications de mon code. Mon référentiel m'appartient toujours, tout comme chaque bit de données et de matériel sur lequel il se trouve, et c'est ainsi que mes applications devraient fonctionner. Grâce à des gens comme Martin, nous savons maintenant comment fabriquer de bons CRDT. Cependant, avant que les applications locales ne soient acceptées comme base, plus de lignes de code devront être écrites.
Dans l'ensemble, il est temps de dire adieu à la transformation opérationnelle. Nous avons passé un bon moment ensemble, de tout ce que j'ai écrit, le code de transformation opérationnelle a été l'un des plus difficiles et des plus intéressants. Vous êtes intelligent et incroyable, OT, mais CRDT peut faire quelque chose que vous ne pouvez jamais. Et j'ai besoin du CRDT. Je pense qu'avec quelques bonnes implémentations, nous pouvons réaliser quelque chose de vraiment spécial.
Je pleure tout le travail que j'ai mis en OT au fil des ans, mais OT ne correspond plus à ma vision de l'avenir. Le CRDT nous permettra de reconstruire Wave plus facilement et plus rapidement et de créer des applications qui traitent les utilisateurs comme des citoyens numériques plutôt que comme des paysans numériques. Et c'est important.
Il est temps de créer.