Atteindre la résilience avec les files d'attente : construire un système qui ne saute jamais un battement sur un milliard
Publié: 2018-12-21Braze traite des milliards et des milliards d'événements par jour pour le compte de ses clients, ce qui se traduit par des milliards de messages hyper ciblés et personnalisés envoyés à leurs utilisateurs finaux. Le fait de ne pas envoyer l'un de ces messages a des conséquences, qu'il s'agisse d'une réception manquée ou, pire encore, d'une notification manquée informant un utilisateur que sa nourriture est prête. Pour s'assurer que ces messages clés sont toujours corrects et toujours à l'heure, Braze adopte une approche stratégique de la façon dont nous exploitons les files d'attente de travaux.
Qu'est-ce qu'une file d'attente de travaux ?
Une file d'attente de tâches typique est un modèle architectural dans lequel les processus soumettent des tâches de calcul à une file d'attente et d'autres processus exécutent réellement les tâches. C'est généralement une bonne chose - lorsqu'il est utilisé correctement, il vous donne des degrés de simultanéité, d'évolutivité et de redondance que vous ne pouvez pas obtenir avec un paradigme traditionnel de requête-réponse. De nombreux travailleurs peuvent exécuter différentes tâches simultanément dans plusieurs processus, plusieurs machines ou même plusieurs centres de données pour une simultanéité maximale. Vous pouvez affecter certains nœuds de travail pour travailler sur certaines files d'attente et envoyer des travaux particuliers à des files d'attente spécifiques, ce qui vous permet d'adapter les ressources selon vos besoins. Si un processus de travail tombe en panne ou si un centre de données se déconnecte, d'autres travailleurs peuvent exécuter les tâches restantes.
Bien que vous puissiez certainement appliquer ces principes et exécuter facilement un système de file d'attente de tâches à petite échelle, les coutures commencent à apparaître (et même à éclater) lorsque vous traitez des milliards et des milliards de tâches. Jetons un coup d'œil à quelques problèmes auxquels Braze a été confronté alors que nous sommes passés du traitement de milliers à des millions et maintenant à des milliards d'emplois par jour.
Le manque de cohérence est une faiblesse
Que se passe-t-il si nous envoyons un message, mais que nous plantons avant d'enregistrer le fait que nous venons d'envoyer ce message ?
Quelques mauvais résultats différents sont possibles ici. Tout d'abord, vous pouvez replanifier le travail ayant échoué et renvoyer le message. Ce n'est… pas idéal : personne ne veut recevoir deux fois la même chose. Au lieu de cela, envisagez de ne pas le reprogrammer du tout. Dans ce cas, notre comptabilité interne sera incorrecte, donc les attributions, les conversions et toutes sortes d'autres choses ne seront plus correctes à l'avenir.
Comment résoudre ce problème ? Lors de la rédaction de nos définitions de travail, nous réfléchissons très sérieusement à l'idempotence et au comportement de nouvelle tentative.
Lorsque vous parlez de files d'attente, l'idempotence signifie qu'un seul travail peut être terminé à un moment arbitraire, le travail remis en file d'attente est réexécuté dans son intégralité et le résultat final sera le même que si nous avions réussi à exécuter le travail exactement un temps. Ceci est intimement lié à notre comportement de choix en matière de nouvelles tentatives - livraison au moins une fois. En gardant à l'esprit que tous nos travaux seront exécutés au moins une fois, et peut-être plusieurs fois, nous pouvons écrire des définitions de travail idempotentes qui garantissent la cohérence même face à des échecs aléatoires.
Pour en revenir à notre exemple d'envoi de messages, comment pourrions-nous utiliser ces concepts pour assurer la cohérence ? Dans ce cas, nous pourrions diviser le travail en deux parties, la première envoyant le message et mettant la seconde en file d'attente, et la seconde écrivant dans la base de données. Dans ce scénario, nous pouvons réessayer l'une ou l'autre des tâches autant de fois que nous le souhaitons. Si le fournisseur d'envoi de messages est en panne ou si la base de données de comptabilité interne est en panne, nous réessayerons de manière appropriée jusqu'à ce que nous réussissions !
De bonnes clôtures font de bons voisins
Qu'arrive-t-il au traitement des données de notre entreprise exemple Consolidated Widgets lorsque la base de données de Global Gizmos est en panne ?
Dans ce scénario, si notre stratégie de livraison au moins une fois est en jeu, nous nous attendrions à ce que tous les travaux de traitement de données pour Global Gizmos recommencent encore et encore jusqu'à ce qu'ils réussissent. C'est formidable - nous ne perdrons aucune donnée même si leur base de données est en panne. Pour Consolidated Widgets, cependant, ce n'est peut-être pas si génial : si les travailleurs réessayent constamment et échouent, ils peuvent être trop occupés pour traiter le travail de Consolidated Widgets en temps opportun.
Nous pouvons résoudre ce problème en utilisant des noms de file d'attente bien choisis et en mettant en pause certaines files d'attente si nécessaire. Avec cela dans notre ceinture à outils, nous pouvons soulager la pression sur les éléments d'infrastructure de manière chirurgicale. Dans notre scénario ci-dessus, une fois que nous savons que la base de données de Global Gizmos est en panne, nous pouvons suspendre leur file d'attente de traitement des données jusqu'à ce que nous sachions qu'elle est de retour, en veillant à ce qu'une panne spécifique n'affecte aucun autre client !
L'attente est douloureuse
Et si Consolidated Widgets et Global Gizmos envoyaient des campagnes par e-mail à 50 millions d'utilisateurs chacun, à 5 minutes d'intervalle ? Qui va en premier?
Les systèmes simples de mise en file d'attente des tâches ont une simple file d'attente de "travail" à partir de laquelle les travailleurs extraient les tâches. Une fois que vous avez une belle variété de travaux et de types de travaux différents, vous passez probablement à plusieurs types de files d'attente, chacune ayant des priorités différentes ou des types de travailleurs tirant de ces files d'attente. Dans cet esprit, nous avons une variété de files d'attente simples pour le traitement des données, la messagerie et diverses tâches de maintenance.
Avance rapide jusqu'au moment où vous envoyez des milliards de messages personnalisés par jour, une file d'attente de « messagerie » ne suffira pas. Que se passe-t-il lorsque cette file d'attente devient extrêmement importante, comme dans notre exemple ci-dessus ? Donnons-nous la priorité aux emplois qui sont arrivés en premier ?
Notre système de mise en file d'attente dynamique cherche à résoudre un phénomène appelé manque de travail, où un travail prêt à être exécuté attend longtemps avant de s'exécuter, généralement en raison d'une sorte de priorité. Dans une simple file d'attente de "messagerie", la priorité est simplement l'heure à laquelle le travail est entré dans la file d'attente, ce qui signifie que les travaux ajoutés à la fin d'une grande file d'attente peuvent finir par attendre très longtemps.
Lorsque nous allons mettre en file d'attente une campagne et tous ses messages, au lieu d'ajouter les travaux à une grande file d'attente de "messagerie", nous créons une toute nouvelle file d'attente pour cette campagne uniquement, avec un nom spécial afin que nous sachions de quoi il s'agit et comment le trouver. Après avoir ajouté les travaux à la file d'attente, nous récupérons notre liste de "files d'attente dynamiques" et ajoutons ce nouveau nom de file d'attente à la fin.
En employant cette stratégie, nous pouvons demander aux travailleurs de choisir le nom d'une file d'attente dynamique dans la liste des « files d'attente dynamiques », puis de traiter tous les travaux de cette file d'attente particulière. Cela nous permet de nous assurer que les messages sont envoyés aussi rapidement que possible ET que tous nos clients sont traités avec la même priorité.
Par conséquent, cela présente d'autres avantages, tels que des taux de réussite du cache plus élevés et moins de connexions à la base de données, en raison de l'augmentation de la localité de travail pour certains travailleurs. Tout le monde gagne !
Toujours avoir un plan de sauvegarde
Que se passe-t-il lorsqu'une base de données est en panne, que certaines files d'attente sont suspendues et que les files d'attente de travaux commencent à se remplir ?
Parfois, des éléments importants de l'infrastructure meurent tout simplement. Nous avons des secondaires et des sauvegardes en place, mais le temps nécessaire pour promouvoir l'infrastructure de sauvegarde n'est presque jamais nul. Avoir plusieurs couches de files d'attente sur l'ensemble de l'infrastructure d'application peut être très utile pour atténuer l'impact de ces types d'événements.
L'une de ces stratégies que nous utilisons consiste à faire la queue sur les appareils eux-mêmes. Des millions et des millions d'appareils ont différentes applications utilisant un SDK Braze, et dans ces applications, nous utilisons une file d'attente pour envoyer des données à nos API.
Lorsque notre SDK va soumettre ces données et échoue, pour une raison quelconque, le SDK met en file d'attente une nouvelle tentative à l'aide d'un algorithme d'interruption exponentielle jusqu'à ce qu'il réussisse. Cette stratégie minimise l'impact des défaillances de l'infrastructure ou du code, car les appareils mettront simplement leurs propres données en file d'attente et les enverront à Braze lorsque tout sera de nouveau en ligne.
Se déplacer rapidement et ne pas casser des choses
En fin de compte, notre objectif est d'envoyer des messages hyper ciblés et personnalisés mieux que quiconque, et cela implique d'agir rapidement, d'être résilient et de tout faire correctement. Les files d'attente de tâches sont au cœur de l'infrastructure de Braze, nous surveillons donc en permanence nos performances, utilisons les meilleures pratiques et expérimentons de nouvelles stratégies et techniques avancées pour être les meilleurs du jeu.
Si ce type d'ingénierie de systèmes hautes performances et à faible latence dans le domaine de l'automatisation du marketing vous passionne, vous devez absolument consulter notre site d'emploi !