Comment Pinterest est passé à 11 millions d’utilisateurs avec seulement 6 ingénieurs
(engineercodex.substack.com)Enseignements
- Utiliser des technologies connues et éprouvées
- Keep it Simple
- Ne pas chercher à être trop créatif (choisir une architecture extensible en ajoutant les mêmes nœuds)
- Limiter les options
- Sharding de base de données > clustering
- S’amuser ! (même les ingénieurs juniors pouvaient contribuer au code dès leur première semaine)
Mars 2010 : bêta fermée, 1 ingénieur
- 1 MySQL + 1 serveur web (Django + Python) + 1 ingénieur (en incluant les 2 cofondateurs). Hébergé sur Rackspace
Janvier 2011 : 10 000 utilisateurs (MAU), 2 ingénieurs
- Stack de serveurs web AWS EC2 (EC2 + S3 + CloudFront)
- Django + Python
- 4 serveurs web pour la redondance
- NGINX comme reverse proxy et load balancer
- 1 MySQL avec 1 secondaire en lecture seule
- MongoDB pour les compteurs
- 1 task queue et 2 task processors (travaux asynchrones)
Octobre 2011 : 3,2 millions de MAU, 3 ingénieurs
- Croissance fulgurante pendant 10 mois, avec un nombre d’utilisateurs qui doublait tous les 1,5 mois
- Le lancement de l’app iPhone en mars 2011 a été l’un des moteurs de cette croissance
- Avec cette croissance rapide, les problèmes techniques sont devenus plus fréquents
- Pinterest a alors commis une erreur : « l’architecture est devenue excessivement complexe »
- Alors qu’il n’y avait que 3 ingénieurs, 5 technologies de base de données différentes étaient utilisées pour les données
- Tout en shardant MySQL manuellement, l’équipe utilisait aussi Cassandra et Membase (aujourd’hui Couchbase) pour clusteriser les données
- Leur « stack trop complexe »
- Stack de serveurs web (EC2 + S3 + Cloudnfront)
- Début de migration du backend vers Flask (Python)
- 16 serveurs web
- 2 moteurs d’API
- 2 proxys NGINX
- 5 bases MySQL shardées manuellement + 9 secondaires en lecture seule
- 4 nœuds Cassandra
- 15 nœuds Membase (3 clusters séparés)
- 8 nœuds Memcache
- 10 nœuds Redis
- 3 routeurs de tâches + 4 task processors
- 4 nœuds Elastic Search
- 3 clusters Mongo
- Stack de serveurs web (EC2 + S3 + Cloudnfront)
- Le clustering s’est mal passé
- En théorie, le clustering permet d’étendre automatiquement le datastore, d’assurer la haute disponibilité et le load balancing, tout en éliminant les SPOF
- Malheureusement, en pratique, le clustering était trop complexe, les mécanismes de mise à niveau étaient difficiles, et il introduisait un gros SPOF
- Chaque base de données possédait un algorithme de gestion de cluster qui assurait le routage entre bases
- Lorsqu’un problème survenait dans la base, il fallait ajouter une nouvelle base et la gérer
- Mais un bug dans l’algorithme de gestion de cluster de Pinterest a corrompu les données sur tous les nœuds, interrompu le rééquilibrage des données et provoqué plusieurs problèmes impossibles à corriger
- La solution de Pinterest ?
- Supprimer du système toutes les technologies de clustering (Cassandra, Membase)
- Miser entièrement sur MySQL + Memcached, plus éprouvés
Janvier 2012 : 11 millions de MAU, 6 ingénieurs
- Environ 12 millions d’utilisateurs et 2,1 millions de DAU
- À ce stade, l’équipe a pris le temps de simplifier l’architecture
- Suppression du clustering et de Cassandra, remplacés par MySQL, Memcache et le sharding
- Stack simplifiée
- Amazon EC2 + S3 + Akamai (à la place de CloudFront)
- AWS ELB (Elastic Load Balancing)
- 90 Web Engines + 50 API Engines (avec Flask)
- 66 bases MySQL + 66 secondaries
- 59 instances Redis
- 51 instances Memcache
- 1 Redis Task Manager + 25 Task Processors
- Apache Solr shardé (à la place d’Elasticsearch)
- Supprimés : Cassandra, Membase, Elasticsearch, MongoDB, NGINX
Comment Pinterest a shardé sa base manuellement
Le sharding de base de données est une méthode qui consiste à diviser un ensemble de données unique en plusieurs bases de données
Avantages : haute disponibilité, load balancing, algorithmes simples pour le placement des données, ajout facile de capacité en divisant la base, recherche des données facilitée
- Comme des problèmes étaient apparus lors du premier sharding, le sharding manuel a été mis en place progressivement sur plusieurs mois
- Ordre de transition
- 1 base + clés étrangères + jointures
- 1 base + dénormalisation + cache
- 1 base + read slaves + cache
- Plusieurs bases shardées par fonction + read slaves + cache
- Bases shardées par ID + backup slaves + cache
- Suppression des jointures de tables et des requêtes complexes au niveau de la couche base de données, avec beaucoup plus de cache
- Comme il fallait énormément d’efforts pour maintenir les contraintes d’unicité à travers l’ensemble des bases, des données comme les noms d’utilisateur et les e-mails ont été conservées dans une énorme base non shardée
- Toutes les tables ont fini par être placées sur des shards
Octobre 2012 : 22 millions de MAU, 40 ingénieurs
- L’architecture a été conservée telle quelle, avec simplement l’ajout de plusieurs systèmes identiques
- Amazon EC2 + S3 + CDNs (EdgeCast, Akamai, Level 3)
- 180 serveurs web + 240 moteurs d’API (Flask)
- 88 bases MySQL + 88 secondaries chacune
- 110 instances Redis
- 200 instances Memcache
- 4 Redis Task Managers + 80 Task Processors
- Apache Solr shardé
- Début de la migration des disques durs vers les SSD
- Enseignement clé : des choix limités et éprouvés (limited, proven choices) étaient préférables
- Le fait de s’en tenir à EC2 et S3 a réduit l’éventail des options de configuration, diminué les casse-têtes et renforcé la simplicité
- En contrepartie, de nouvelles instances pouvaient être prêtes en quelques secondes. Autrement dit, il était possible d’ajouter 10 instances Memcache en quelques minutes seulement
Structure de base de données de Pinterest
- IDs
- Comme Instagram, Pinterest avait une structure d’ID unique à cause du sharding
- Composition de l’ID 64 bits
- Shard ID : indique de quel shard il s’agit. 16 bits
- Type : type d’objet (comme un Pin) 10 bits
- Local ID : position dans la table. 38 bits
- La structure de lookup de cet ID n’était qu’un simple dictionnaire Python
- Tables
- Il y avait des tables d’objets et des tables de mapping
- Les tables d’objets servaient pour les pins, boards, commentaires, utilisateurs, etc. : local ID mappé vers un MySQL Blob (JSON)
- Les tables de mapping servaient aux données relationnelles entre objets, comme associer un board à un utilisateur ou un like à un pin : full ID mappé vers full ID et horodatage
- Toutes les requêtes passaient par des recherches de PK (clé primaire) ou d’index pour l’efficacité. Toutes les jointures ont été supprimées
1 commentaires
Comment Instagram a conquis 14 millions d’utilisateurs avec seulement 3 ingénieurs
C’est un article de la même série, et le contenu s’enchaîne aussi.
« Garder les choses simples. Utiliser des technologies connues et éprouvées »