Mise à jour des vues à l’enregistrement avec CouchDB

Ah CouchDb ! Ce formidable SGBD NoSQL orienté documents à stockage JSON, à API HTTP, utilisant JavaScript pour les index / vues MapReduce... Nous pourrions continuer les buzzwords mais stop ici 😉

Il a un soucis ! Si vous, cher lecteur, avez l'habitude des SGBD SQL, vous allez découvrir avec stupeur que les index (plus couramment appelés les vues) ne sont pas mis à jour dès la modification / insertion / suppression de documents ... Mais à la prochaine interrogation de la vue dans laquelle le document est indexé. Et ce n'est pas une option.

La raison est louable, c'est pour des questions de performances. Il est plus rapide et économe d'indexer 100 documents qui n'ont pas été accédés depuis la dernière indexation de la vue en une seule fois, que d'indexer progressivement 100 fois 1 seul des 100 documents pour rien, en attendant leur prochaine lecture.

Dans les applications faisant d'avantage d'écritures que de lectures, c'est un problème. Imaginez une application de type Feedly, qui agrègent des flux RSS de plusieurs centaines d'utilisateurs. Quand un utilisateur clique sur un flux, il doit pouvoir consulter immédiatement les news de ce celui-ci. La nuit, les utilisateurs sont peu nombreux, il y a peu de requêtes de consultation, mais potentiellement beaucoup d'insertions entre ces dernières, car les sites web dans un fuseau horaire différents continuent de générer des actualités. Il serait impensable qu'un de vos rares utilisateurs nocturne doive attendre plusieurs secondes voir plusieurs minutes, lors de sa première requête, le temps que l'indexation de la vue des actualités de tous les utilisateurs soit finie ...

Le problème se manifeste aussi dans les applications ayant des mises à jour / insertions / suppressions en batch. Imaginez un job nocturne réduisant les prix de 10000 produits d'un catalogue e-commerce, le premier utilisateur suivant la mise en place de la promotion ne devra subir la ré-indexation des vues impactées.

Solutions

La première solution, partielle, est d'interroger les vues avec le paramètre stale (https://wiki.apache.org/couchdb/HTTP_view_API). La vue interrogée n'est pas mise à jour, mais ne retournera pas la dernière version indexée des documents. Dans la majorité des cas, cela ne semble pas envisageable. Dans notre exemple Feeldy, cela pourra se traduire par un flux affichant 10 actualités non lues, mais lors de son ouverture, il semblerai vide. Dans notre exemple e-commerce, cela se traduirai par un visiteur voyant une pub -20% sur tout le site sur la page d'accueil, mais les prix affichés seraient les anciens, en attendant la mise à jour des vues. Mais quand se lancera t-elle ? Si toutes les requêtes des visiteurs sont stale, l'indexation ne se lance pas.

Il  alors possible d'interroger toutes les vues impactées par la modification d'un document (juste pour lancer l'indexation, sans utiliser leur résultat), juste après celle-ci, ou après l’exécution d'un batch. Ainsi, tout sera en permanence à jour. Et si les requêtes des visiteurs du site e-commerce sont stale, ils verront les nouveaux prix quand l'indexation sera finie. Mais il y a probablement beaucoup de bricolage à faire dans le code de l'application, dans la couche d'accès aux données.

La troisième solution consiste à faire un job qui interroge régulièrement toutes les vues devant être à jour. Cette solution n'est pas parfaite car si l’intervalle est de 5 minutes, que 10 000 prix sont mis à jour, et qu'un visiteur arrive sur le site avant l'exécution du job, c'est comme s'il ne servait à rien. Le visiteur va déclencher l'indexation et probablement subir un timeout HTTP. Et juste après le job se lancera, mais tout aura déjà été mis à jour ...

La solution la plus efficace est à mi-chemin entre les 3 premières et ne nécessite aucune modification dans l'application. Elle consiste à mettre un "trigger" sur CouchDB, permettant de lancer l'indexation de toutes les vues critiques par consultation sur celles-ci après la modification de X documents, qu'importe la vue. Ainsi les temps d'attente que vont subir les requêtes clientes seront courts. Mais plusieurs vues sont indexées à chaque fois, et potentiellement des vues qui n'ont pas été impactées. C'est un compromis.

Il semble y avoir plusieurs mécanismes pouvant aider à cette solution (je n'ai essayé que le dernier) :

Le sujet est abordé ici : http://wiki.apache.org/couchdb/Frequently_asked_questions?action=show&redirect=FrequentlyAskedQuestions#update_views_more_often

Sources

http://wiki.apache.org/couchdb/Regenerating_views_on_update?action=show&redirect=RegeneratingViewsOnUpdate

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.