Dans un article publié récemment sur son blog, Grab engineering partageait son expérience sur la conception de sa plateforme de données backend.
GrabApp est une application qui permet aux clients de sélectionner et d'acheter des produits de tous les jours auprès de leurs commerçants. Pour être évolutive et gérable, la plate-forme de données distribuées et l'ingestion doivent être tolérantes aux pannes. Pour concevoir ce système, comme expliqué dans l'article publié sur le blog, ils ont classé les requêtes en deux classes principales. Ils ont rédigé des requêtes comme s'ils créaient et mettaient à jour une commande, lu des requêtes pour obtenir un numéro de commande (orderID), traduit les statistiques associées à l'utilisateur ID, etc. On peut facilement ranger ces deux types de requêtes en lecture/écriture comme s'il s'agissait de requêtes transactionnelles et analytiques.
Les requêtes transactionnelles sont également appelées OLTP ou Traitement Transactionnel En Ligne (en anglais Online Transactional Processing). Et les requêtes analytiques sont appelées OLAP ou Processus Analytique En Ligne (en anglais Online Analytical Processing). Ces deux types de stockage de données et leur utilisation sont illustrés dans la figure suivante :
Plate-forme de base de données pour une commande passée en ligne dans Grab
Pour les requêtes transactionnelles, les ingénieurs ont utilisé AWS DynamoDB. DynamoDB est une base de données clé-valeur élastique et évolutive. Elle supporte une clé primaire forte et durable. Ci-dessous un exemple de table DynamoDB :
Comme expliqué dans l'article publié sur le blog :
Chaque table DynamoDB comporte de nombreux éléments avec attribut. Chaque élément contient une clé de partition et une clé de tri. La clé de partition est utilisée pour les requêtes clé-valeur et la clé de tri est utilisée pour les requêtes de plage. Dans notre cas, la table contient plusieurs articles de commande. La clé de partition est l'ID de commande. On peut facilement supporter les requêtes clé-valeur grâce à la clé de partition. Les requêtes par lot telles que "Consulter les commandes en cours par identifiant" sont supportées par DynamoDB Global Secondary Index (GSI). Un GSI est comme une table DynamoDB normale qui possède également des clés et des attributs.
En utilisant DynamoDB, les ingénieurs se sont servis des attributs de durée de vie (TTL) pour gérer la rétention. Ils ont ainsi pu contrôler la taille de la table et le coût.
Quant aux requêtes analytiques, les ingénieurs de Grab ont utilisé MySQL. Les graphiques suivants montrent l'architecture OLAP.
Utilisation de Kafka pour connecter le flux de données aux magasins de données OLTP et OLAP
On utilise Kafka pour traiter les données de flux correspondant aux données OLTP et OLAP. Amazon Simple Queue Service (SQS) est utilisé pour les nouvelles tentatives et donc garantir une fiabilité et une disponibilité élevées de Kafka.
L'article publié sur le blog l'explique ainsi :
Même si Kafka peut fournir un SLA à 99,95 %, il existe toujours un risque de défaillance du producteur de flux. Lorsque l'API de producteur Kafka échoue, on stocke le message dans un Amazon Simple Queue Service (SQS) et on ré-essaie. Si la nouvelle tentative échoue également, elle sera déplacée en file d'attente de lettres mortes SQS (DLQ), pour être consommée ultérieurement. Du côté du consommateur de flux, on utilise une nouvelle tentative d'interruption au niveau du flux et de la base de données pour garantir sa cohérence. Dans le pire des cas, on peut rembobiner les événements de flux de Kafka. Il est important que le pipeline d'ingestion de données gère les messages en double et les messages en désordre. Les messages en double sont gérés par la clé unique au niveau de la base de données (par exemple, ID de commande + heure de création).
La conception d'une architecture à deux couches pour les plates-formes de données comme celle de OLTP et OLAP est un moyen clair de s'assurer que l'équipe d'ingénierie est capable de se concentrer sur l'évolutivité, la disponibilité et l'observabilité élevées de ces deux couches.