REX Storm Redis

1 389 vues

Publié le

Retour d'expérience sur l'utilisation de Storm et Redis sur le projet twitter-foot pour l'Agence France Presse

Publié dans : Ingénierie
2 commentaires
4 j’aime
Statistiques
Remarques
Aucun téléchargement
Vues
Nombre de vues
1 389
Sur SlideShare
0
Issues des intégrations
0
Intégrations
180
Actions
Partages
0
Téléchargements
18
Commentaires
2
J’aime
4
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

REX Storm Redis

  1. 1. REX STORM REDIS
  2. 2. •Les besoins du projet AFP twitter-foot •Présentation de Redis •Manipuler des tweets avec Storm •Implémenter des fenêtres glissantes •Testabilité du cluster •Monitoring et supervision •Débogage et bonnes pratiques
  3. 3. •Plus de 7000 comptes twitter référencés par l’AFP •5 ligues de football suivies •Jusqu’à 170 tweets par seconde •Recherche de tendances sur les hashtags •Classements de popularité de joueurs / équipes et panelistes •Des timelinesde tweets par ligue, par équipe et par matches en live
  4. 4. Redis Twitter Feeder Serveur REST pour front-end Serveur workersStorm Serveur Zookeeper + Storm nimbus
  5. 5. •Utilisation de Storm pour le tri des tweets reçus, et la recherche de mots clé •Utilisation de Redis comme queue pour le flux d’entrée •Utilisation de Redis pour la gestion et le stockage des timelines •Serveur Web Services REST (Jetty) Cluster de 7 serveurs en toutpour le backend
  6. 6. REDIS
  7. 7. •Datastorede type Key / Value •Données en RAM uniquement •Implémentation en C ANSI •Monothreadé •Support de publish/ subscribe •Communication sur TCP avec protocole spécifique •Nombreux clients disponibles en divers langages •Sponsorisé par Pivotal
  8. 8. Parmi les applications reposant sur redis on retrouve: StackOverflow, Github, Pinterest, Flickr, Snapchat… et Twitter! Redis est notamment utile pour •Améliorer les performances d'une base de données (MySQL, MongoDB…) •Gérer finement un cache applicatif •Traiter des statistiques et des classements •Servir de Message Broker et gérer des notifications entre applications Redis est un vrai couteau suisse!
  9. 9. "Bad programmers worry about the code. Good programmers worry about data structures and their relationships." L. Torvalds Structures disponibles •Les sets •Les listes •Les hashes •Les strings •Les bitmaps •Les HyperLogLogs •Les Sorted Sets
  10. 10. •Notion de score par élément (stocké en tant que "double" soit 64 bits mais 53 bits significatifs seulement) •Récupération d’un ensemble d’éléments par leurs positions ou leurs scores •Implémentation via des skip-listset des hashsetsassurant des performances élevées •Utilisation documentée permettant notamment de calculer avec précision le coût des requêtes effectuées •La performance élevée implique néanmoins une occupation mémoire supérieure aux structures classiques
  11. 11. •ZADD ajoute un élément à un ZSET avec un score •ZINCRBY incrémente le score d'une valeur choisie •ZRANGE récupère une plage d'éléments par leur index défini par leur score (plus petit au plus grand): idéal pour un classement (les 10 meilleurs par exemple) •ZRANGEBYSCORE récupère une plage d'éléments dans un intervalle de scores (score entre 5 et 10…)
  12. 12. redis>ZADD myzset1 "one" (integer) 1 redis>ZADD myzset2 "two" (integer) 1 redis>ZINCRBY myzset2 "one" "3" redis>ZRANGE myzset0 -1 WITHSCORES 1) "two" 2) "2" 3) "one" 4) "3" redis>ZADD myzset1 "one" (integer) 1 redis>ZADD myzset2 "two" (integer) 1 redis>ZADD myzset3 "three" (integer) 1 redis>ZRANGEBYSCORE myzset-inf+inf 1) "one" 2) "two" 3) "three" redis>ZRANGEBYSCORE myzset1 2 1)"one" 2) "two"
  13. 13. •Utilisation de tweets comme valeurs dans un ZSET et utilisation du Tweet ID comme score •Timelinesde tweet ordonnancées par tweetid: chronologie respectée •Plus récent: tweet id le plus élevé (snowflakele garantit) •Utilisation de tweets comme valeurs dans un ZSET et du nombre de retweets comme score •Classement des tweets les plus retweetés
  14. 14. 22:04:41:524652515665915905:nicolas_vilas:RTcount=0:Une action de David Luiz qu'on risque de revoir... en boucle #APOELPSG profiles=["JRNL"] teams=["NEUTRAL"] leagues=["FRAL1"] 22:04:33:524652479569752065:NikoB19:RTcount=0:Tous les matchs sur Bein(sauf Porto -Bilbao) sont joués, je file à la douche en espérant un but parisien. profiles=["BLOG"] teams=["LENS"] leagues=["FRAL1"] 22:04:23:524652438729416704:PSG_inside:RTcount=31:57' Sauvetage de @DavidLuiz_4 sur la ligne Parisienne ! Corner pour l'@apoelfcofficial. #APOELPSG profiles=["TEAM"] teams=["PSG"] leagues=["FRAL1"] 22:04:11:524652387664158720:Gibney_A:RTcount=1:WOW. So close to a goal. David Luiz clearsa header off hisownline. profiles=["JRNL"] teams=["LILL"] leagues=["FRAL1"] 22:04:08:524652374439493632:RemDenjean:RTcount=0:#Maxwell est vraiment un très grand footballeur: professionnel, classe, talentueux, combattif... L'une des meilleures recrues du PSG 2.0! profiles=["TEAM"] teams=["TOUL"] leagues=["FRAL1"] Score 524652515665915905 Score 524652479569752065 Score 524652438729416704 Score 524652387664158720 Score 524652374439493632 ZSET "timeline" Les valeurs contiennent le JSON Les scores sont les tweet ids
  15. 15. Les opérations sur ZSET sont majoritairement en O(log(N)) •ZSCORE est en O(1) •ZADD est en O(log(N)) avec N le nombre d'éléments dans le ZSET •ZINCRBY est en O(log(N)) avec N le nombre d'éléments dans le ZSET •ZRANGE est en O(log(N) + M) avec N le nombre d'éléments dans le ZSET et M le nombre d'éléments retournés
  16. 16. •Clusterisationen beta ou à faire manuellement, difficile à réaliser •Pas de "rollbacks" de transactions •La persistance des données a un impact sur les performances dans les deux modes proposés •Le mode par défaut de persistance peut perdre des données en cas de crash •Tout est en mémoire RAM, attention aux leakset aux Out-of-memory! •Pas de version windowsofficielle (mais il existe un port) •Intégration à Java minimale mais suffisante (Jedis, Spring-redis)
  17. 17. •Les tweets idssont ordonnancés chronologiquement (snowflake), les timelinessont faciles à gérer via des SortedSet •Utilisation du tweet id comme score pour les timelines •Utilisation du tweet id comme valeur pour les autres classements (retweets, mots-clé…) •Performances élevées en accès aux données et en débit •Un datastoreà la complexité modérée et au coût d'entrée faible •Intégration facile avec Storm •Perdre quelques tweets n'est pas (si) important
  18. 18. STORM
  19. 19. 1.Utilisation de la connexion hosebirdvers twitter alimentant une queue redis 2.Récupération des messages twitter depuis Redis via un Spoutdédié 3.Définition de divers streamsen Storm pour le traitement des tweets 4.Stockage des résultats dans Redis Twitter-feeder Hosebird Redis SpoutStorm "Raw" BoltStorm Alimentation Queue Dirty check queue Emission des tuples Twitter Création des streams
  20. 20. Redis Twitter Feeder Serveur REST pour front-end Serveur workersStorm Serveur Zookeeper + Storm nimbus
  21. 21. •Recherche de mots-clédivers •Classement de joueurs via liste de mots clé •Classement d'équipes •Classements des hashtags populaires •Classements des tweets les plus retweetés •Classements des comptes twitter les plus actifs •Recherche de médias: images / vidéos •Croisement avec des données journalistiques du bureau des sports
  22. 22. •Configuration stockée en JSON dans Redis •Spoutsde configuration sur divers thèmes •Dirty check de clés de configuration sur Redis •Envoi de la nouvelle configuration en tant que tuplesi changement détecté Redis Spoutde configuration Boltsabonnés au Stream de configuration Dirty check de la configuration Serveur manager des configurations Changement de la configuration dans redis
  23. 23. Pour améliorer les performances, plusieurs solutions: •Augmenter le nombre d'Executors •Augmente le nombre de threads s'exécutant sur le Bolt/ Spoutconcerné dans le cluster •Limitation par le nombre de CPU disponibles sur le cluster avec / sans Hyperthreading •Augmenter le nombre de Tasks •Revient à augmenter le nombre d'instances du Bolt/ Spoutconcerné dans le cluster •Changer le design applicatif / algorithmes utilisés
  24. 24. Le livrable de Storm est simple: Jar contenant la topologie •Peu lié aux spécificités du runtimedu cluster Storm •Corriger une erreur de design interne est donc plus facile lors des montées de version •Le refactoringest donc encouragé La difficulté dans l'usage de Storm se trouve autant dans le développement que dans l'administration du cluster. Plusieurs options (cumulables): •Soyez / devenez DevOps •Chouchoutez votre administrateur système / réseau •Optez pour une solution Cloud
  25. 25. Fenêtres glissantes
  26. 26. •Parcours d'un itérablesur un nombre fixe de n éléments •Cet itérableest peuplé de nouvelles données au fur et à mesure •Eviction des données trop anciennes •Utilisation possible pour le calcul de débits en "live" •Bande passante utilisée •Occurrence de mots clé
  27. 27. •Choix d'une durée pour la fenêtre •les 15 dernières minutes •Choix d'une fréquence de calcul •MAJ toutes les 5 secondes •Comptage du nombre de tweets dans une structure adaptée •Rolling buffers, zsets… •Le résultat donne un quotient de tweets par seconde •débit "live" de 35 tweets par seconde basé sur le nombre de tweets reçus des 15 dernières minutes, recalculé toutes les 5 secondes
  28. 28. Storm peut servir à calculer des fenêtres glissantes (SlidingWindow) •Chaque donnée possède un timestampqui permet de calculer son éligibilité aux fenêtres glissantes •Un buffer en mémoire représentant la fenêtre glissante compte les occurrences d'une donnée choisie sur une période donnée •Une tâche calcule le débit à intervalle régulier Deux outils sont fournis et documentés avec Storm pour cet effet •Les Ticktuples •Les rollingbuffers
  29. 29. •Un Boltde type "Map" émet des éléments individuellement •Un Boltde type "Reduce" s'abonne au Bolt"Map" en fieldgrouping •Stockage dans un buffer in-memory des éléments reçus et du nombre de leurs occurrences •Emission d'un Tuple"résumé" périodiquement grâce aux TickTuples •Un Boltde type "Ranker" récupère les résultats de tous les types "Reduce" et calcule le résultat
  30. 30. Pour réaliser une SlidingWindowen Redis, il suffit de stocker les données brutes de comptage en tant que ZSET sur une unité de temps choisie (minute, heure, jour…) Quand on désire calculer les valeurs finales, il suffit de réaliser un ZUNION qui additionne les clés ZSET choisies en produisant un ZSET des résultats Ronaldo:1 Ribery:2 Messi:1 Ronaldo:3 Messi:2 Ronaldo:4 Messi:3 Ribery:2 players:23h00 players:23h01 players:23h02 players:current-ranking ZUNION des 3 dernières minutes Exécution toutes les minutes
  31. 31. Implémentation Storm •Permet de faire du Map-Reduceefficacement •Nettoyage des buffers auto-gérépar les structures fournies •Utilise la RAM JVM, ce qui peut donner un Out-of-memory détruisant le Workeret pouvant perdre les données du buffer en cours Implémentation Redis •Données brutes dans Redis: facilement auditable •Pas de pertes de buffers lors d'un crash de workerStorm •Utilise la RAM Redis, attention au Out-of-memory •Nettoyage des valeurs dans Redis manuel •Ajoute de la charge sur Redis
  32. 32. Testabilité
  33. 33. •Technique permettant de valider une fonctionnalité par l'exécution de tests (avec succès) •S'apparente à un test de type "boîte noire" en mode End-to-End •Il est possible d'intégrer ce mode de validation dans un processAgile
  34. 34. •Framework de tests permettant la mise en place de tests d'acceptance •Ecrit originellement en Ruby mais porté en Java (entre autres) •Utilisation de Domain SpecificLanguage(DSL) pour décrire les tests •Fonctionne avec JUnit, Mockito
  35. 35. Feature: Top N of playersin the global timeline. Scenario Outline: : Player appearsin the tweet. Givena panelistfor the league"<League>" And the playerkeyword is"<Keyword>" Whenthe panelisttweets "<Tweet>" Thenthe global playercounterof "<Keyword>" is1 Examples: | League | Keyword | Tweet | | FRAL1 | Lucas Deaux| Le milieu Lucas Deauxest la révélation de cette année | | ENGL1 | ZatKnight | The best central defender isZatKnight | Scenario: Player appearsin the beginningof the tweet. Givena panelist And the playerkeyword is"Djordjevic" Whenthe panelisttweets "Djordjevicne restera malheureusement pas nantais l'an prochain" Thenthe global playercounterof "Djordjevic" is1
  36. 36. •Cucumberest appelé depuis un Test JUnit(Runnerspécifique) •La featureCucumberest parsée •Une classe "StepDefs" Java est appelée par Cucumber •Cucumbermatche les phrases du scénario à des méthodes Java •Via des annotations: @Given@When@Then •Utilisation de RegExp: "^the global player counter of "([^"]*)" is (d+)$" •Cucumberexécute les méthodes et injecte les paramètres définis dans le scénario •JUnitdonne le résultat du test
  37. 37. Le déroulement d'un test donne 1.Une phase de préparation démarre la topologie et initialise les données dans le Redis de test 2.L'exécution du scénario de test simule l'arrivée d'un tweet forgé dans Redis 3.L'application Storm dans le cluster local de test traite le tweet et stocke le résultat dans le Redis de test 4.L'assertion définie dans Cucumberest exécutée et donne un reporting, par exemple un polling sur Redis vérifiant la valeur d'un compteur 5.Si la featureCucumbercontient d'autres scénarios ils sont exécutés 1 à 1 6.La phase terminale du test stoppe le cluster et nettoie le redis de test La topologie de test n'est donc pas redémarrée à chaque test ("scenario") pour diminuer le temps d'exécution
  38. 38. Il est souhaitable d'avoir des tests End-to-End dans une application Storm pour •Faciliter le débogage •Documenter les fonctionnalités •Eviter les régressions Néanmoins les tests sont coûteux à maintenir au fil des évolutions de l'applicatif •Les tests avec mockscomplexes sont "fragiles" •La non maintenance des tests signifie leurs morts •Sans implication d'un membre de la partie métier, cela ne restera qu'un outil de développeur
  39. 39. Monitoring Supervision
  40. 40. •Serveur Zookeeperde coordination •Storm-nimbus •Storm-supervisors •Storm-workers •Redis •Serveurs REST pour le front-end
  41. 41. •Création d’artifactszip via Mavenpour chaque serveur •Scripts pour toutes les tâches courantes (MAJ configuration, restart, etc)
  42. 42. •Scripts de redémarrage de process •Supervision du CPU et de la RAM •DSL avancé de configuration check processredis-server withpidfile"/var/run/redis.pid" startprogram = "/etc/init.d/redis-server start" stop program = "/etc/init.d/redis-server stop" if 2 restartswithin3 cycles thentimeout if totalmem> 7000 Mb thenalert if cpuusage > 95% for 3 cycles thenrestart if failedhost 127.0.0.1 port 6379 thenrestart if 5 restartswithin5 cycles thentimeout
  43. 43. Redis-rdb-toolsest un parserde dump Redis de type "RDB" •Permet l'audit des clés d'une instance en mode "offline" •Calcul approximatif de l'espace occupé de chaque clé de l'instance
  44. 44. Redmonet RedisLivesont des outils de monitoring de Redis en live •Accès au slowlog(requêtes les plus longues) •Informations sur la mémoire (occupation, fragmentation) •Aperçu des structures de données utilisées dans l'instance
  45. 45. Debugmode Best practices
  46. 46. L'architecture Storm + Redis est très distribuée, par conséquent fixer (trouver) un bug peut devenir un vrai challenge Pour éviter un coût de maintenance élevé et s'assurer la pérennité de l'application, il faut éviter de cumuler les problématiques au même endroit L'outil Sonar est un moyen utile de surveiller le projet
  47. 47. •Séparer l'action (Boltd'action) de la condition (Boltde contrôle) •Séparer l'insertion de résultat dans Redis de son nettoyage •Utiliser des design patterns: Strategy, Chain of Responsibility… Une séparation plus extrême consiste à définir plusieurs topologies •Communication entre topologies assurées par un élément externe (Redis par exemple) •Audit facilité des problèmes •Meilleure testabilité •Meilleure maintenabilité •Meilleure robustesse •Nécessite plus de workersStorm (1 workerne sert qu'une seule topologie) •Permet de faire de la pseudo QoSsur des topologies
  48. 48. •Tracer les tuplesnaviguant dans une topologie est utile •Débogage plus facile •Audit de performances •Ajouter un objet "espion" dans chaque streampeut servir à cet effet •Ajouter le nom de chaque Bolttraversé •Chronométrer le temps passé dans chaque Boltou méthode de Bolt •Garder une trace de certains tests métier •Certains bugs sont difficiles à reproduire avec Storm, aussi, avoir de bons logs peut grandement aider aux fixes
  49. 49. •Redis est un stockage temporaire dans notre modélisation •Chaque entrée doit être nettoyée à un moment donné •Il est important d'être rigoureux dans le référencement de clés afin d'éviter les leakset de faciliter le débogage •Le format des données insérées est aussi important, l'utilisation de standards peut grandement aider: json-schema, XSD, DTD… •Une bonne méthode est de séparer les tâches d'insertion des tâches de suppression •Bolts/ Spoutsdifférents •Topologies différentes
  50. 50. •Redis supporte Luanativement •Comme Redis est monothreadé, aucune requête redis n'est effectuée pendant l'exécution d'un script Luaen parallèle •Un script Luaest donc atomique sur une instance Redis •Luapermet d'éviter des round-trips réseau •Possibilité d'utiliser la librairie cjsonen Luaainsi que MSGPACK qui permet de compresser les données JSON
  51. 51. Questions

×