- L’avenir des services de données cloud repose sur une architecture « à grande échelle, multi-tenant »
- Si des services SaaS de premier plan comme S3 offrent simplicité, fiabilité, durabilité, scalabilité et faible coût, c’est parce que leurs technologies ont été conçues structurellement pour fournir ces propriétés
- Fournir un service aux clients via un vaste pool de ressources garantit des gains d’efficacité et de fiabilité liés à l’échelle
[Définition des systèmes serverless multi-tenant (Serverless Multi Tenant)]
Définition de la « multi-tenancy »
- La multi-tenancy consiste à mutualiser les ressources en co-localisant les charges de travail sur un matériel partagé
- Construire un système dans le cloud signifie que plusieurs tenants sont servis soit par des instances de calcul partagées (par ex. Amazon EC2 ou Google Compute), soit par des services PaaS partagés (par ex. le stockage d’objets cloud)
- La multi-tenancy est définie ici comme « le fait de fournir un service à plusieurs tenants à partir de ressources partagées (serveurs virtualisés, disques et services de base PaaS, etc.) »
- Plusieurs modèles de partage des ressources sont possibles, et certains systèmes combinent plusieurs modèles à travers l’ensemble des composants
- Processus partagé : le même processus logiciel sert plusieurs tenants. L’isolation des données et de la sécurité est logique
- Conteneurs : exécution d’un nœud mono-tenant et empaquetage de plusieurs conteneurs par hôte. Cela se fait généralement via Kubernetes, où un nœud K8s donné héberge les pods de nombreux tenants
- Virtualisation : exécution d’un nœud mono-tenant dans une VM (par ex. QEMU) ou une microVM (par ex. Firecracker), avec plusieurs VM empaquetées par hôte. Kubernetes peut aussi être utilisé avec des VM via Kata Containers
- Il existe aussi une méthode d’isolation V8 permettant à des tenants de partager le même processus V8 tout en s’exécutant dans des contextes légers séparés, mais je ne l’ai pas encore vue dans les systèmes de données
Définition du serverless
- Le client ne choisit pas le type de serveur et ne sélectionne pas explicitement le matériel
- Ces systèmes s’appuient sur un certain niveau d’élasticité et de mobilité pour absorber la demande de toutes les charges de travail, sans que le client ait à ajuster explicitement la taille du matériel
- Élasticité : capacité à augmenter ou réduire le service selon les besoins de la charge de travail
- Mobilité : capacité du service à déplacer et équilibrer en interne les charges de travail afin de respecter les exigences de performance et de fiabilité
- Le modèle serverless utilise une facturation à l’usage, de plus en plus importante pour les clients
- Beaucoup de clients ne veulent pas s’engager à grande échelle à l’avance et préfèrent simplement payer pour ce qu’ils consomment
- La facturation à l’usage peut prendre de nombreuses formes, qui varient fortement selon la charge de travail et l’implémentation sous-jacente du système
- Paiement par (million d’) opérations
- Paiement pour l’utilisation CPU et mémoire de la charge de travail
- Paiement par Go de stockage
- Paiement pour des unités virtuelles de performance/capacité liées aux ressources et au débit de travail (par ex. les RCU/WCU de DynamoDB)
- Modèles hybrides où le client paie une certaine capacité de base, puis paie au-delà de cette utilisation (« payer la base, payer les pics »)
[Défis communs]
Travailler dans les contraintes imposées par la charge de travail
- Les nombreuses contraintes imposées par la charge de travail d’un système de données donné sont des moteurs majeurs de l’architecture sous-jacente.
- Exigences de latence / de disponibilité
- Exigences de cohérence
- Corrélations / dépendances entre les requêtes et les données
- Modèles d’accès séquentiel versus aléatoire
- Variété du travail effectué par requête
- Taille des données
- Protocoles orientés session versus orientés requête, mécanismes push versus pull
- Intensité de calcul du travail
- Des exigences moins strictes en matière de latence et de cohérence offrent plus de liberté aux ingénieurs
- Un bon exemple est l’intérêt du stockage d’objets cloud, peu coûteux et très durable, dans les systèmes où la faible latence est moins critique, car les systèmes à faible latence sont contraints dans l’introduction de composants à latence élevée
- Un système eventually consistent peut éviter ce dilemme en écrivant les données de manière asynchrone dans le stockage d’objets, sans l’inclure dans le hot path synchrone des données
- Les systèmes à faible latence et à forte cohérence ne disposent pas de cette carte joker
- Lorsque des contraintes comme la faible latence se combinent, la localité spatiale et temporelle de la charge de travail peut influencer les choix architecturaux
- Par exemple, pour une charge de travail caractérisée par des scans séquentiels, il est préférable de conserver ensemble des plages de données contiguës afin de permettre des scans rapides et efficaces sur disque
- Fractionner ces plages en sous-plages plus petites aide à gérer les hotspots, mais ces deux objectifs sont contradictoires, et il faut donc trouver un équilibre
- Des modèles d’accès aléatoire avec peu de corrélation entre les requêtes individuelles peuvent tirer parti d’un espace d’adressage plat, réparti uniformément et finement sur plusieurs serveurs
- Les protocoles orientés session qui établissent des connexions persistantes sont généralement plus difficiles que les protocoles orientés requête, où chaque requête est indépendante de la précédente
- Les connexions persistantes peuvent nécessiter du connection pooling, et des perturbations comme le rolling des nœuds ou l’équilibrage des données peuvent avoir un impact extérieurement visible pour les clients
- Certains systèmes disposent d’une API de stockage simple, comme le stockage d’objets ou l’API Kafka, tandis que d’autres, comme les bases de données SQL, sont très intensifs en calcul
- Cela conduit au sujet de la prévisibilité et de la variabilité de la quantité de travail nécessaire pour traiter chaque requête
- À une extrémité, on trouve des API de streaming de données comme Kafka, où il suffit de récupérer un bloc contigu d’enregistrements ; à l’autre, SQL, où la charge de travail peut varier fortement d’une requête à l’autre
Isolation des tenants
- Le partage des ressources augmente l’utilisation du matériel, mais peut entraîner des contentions de ressources où la charge de travail d’un tenant affecte les autres
- Dans un système multi-tenant, il faut garantir que les tenants servis sur des ressources matérielles partagées bénéficient d’un niveau de service équivalent à celui d’un service dédié
Séparation du stockage et du calcul
- La séparation du stockage et du calcul est un principe de conception central, mis en œuvre à des degrés divers dans tous les systèmes étudiés jusqu’ici
- Les tendances matérielles rendent cette séparation de plus en plus réaliste, en partie parce que le réseau n’est plus le goulet d’étranglement qu’il était autrefois
- Le débit réseau augmente, mais de nouveaux défis liés à cette séparation persistent, notamment du fait de la place centrale prise par le stockage d’objets cloud
- Le stockage d’objets cloud reste relativement lent, mais il offre une grande durabilité à faible coût
- En revanche, il peut être difficile à introduire dans des charges de travail généralement sensibles à la latence, comme les bases de données OLTP
- De plus, le modèle économique du stockage d’objets cloud pénalise les architectures qui reposent sur de très nombreux petits objets ; il faut accumuler les données dans des objets plus gros avec moins de requêtes, ce qui complique encore le cycle de vie des systèmes à faible latence
- Les ingénieurs peuvent intégrer le stockage d’objets dans des systèmes à faible latence tout en répondant au problème de latence en plaçant devant lui un cache d’écriture durable et tolérant aux pannes, ainsi qu’un cache de lecture prédictif
- Ce cache d’écriture durable est essentiellement un cluster de serveurs qui implémente un protocole de réplication et écrit les données dans du block storage
- En arrière-plan, le cluster téléverse les données de manière asynchrone vers le stockage d’objets selon un modèle économique consistant à écrire un plus petit nombre de gros fichiers
- Un cache d’écriture tolérant aux pannes prend bien en charge les écritures à faible latence
- Dans cette architecture, le cache de lecture peut être plus problématique
- Les charges de travail séquentielles, comme l’event streaming, sont simples et très efficaces
- Tant que l’Aggregate Prefetching suit la demande, les lectures devraient toujours aboutir dans le cache de lecture local
- Les bases de données font face à un problème plus difficile en raison de modèles d’accès aléatoire difficiles à prédire, même si les scans de table peuvent toujours bénéficier de la lecture anticipée
- Mettre en œuvre un cache d’écriture distribué, tolérant aux pannes, via un protocole de réplication n’a rien de simple, et dans un environnement multi-AZ cela peut aussi entraîner d’autres coûts, comme les frais inter-AZ
- Mais pour l’instant, il n’existe pas d’alternative pour les systèmes à faible latence qui veulent utiliser un stockage d’objets peu coûteux et durable comme stockage principal des données
- D’autres systèmes à faible latence doivent éviter complètement le stockage d’objets cloud et privilégier avant tout une latence faible et prévisible
- Le stockage cloud est largement utilisé, mais il n’est pas universel en raison des compromis sur la latence.
Gestion des hotspots
- La gestion des hotspots consiste à répartir la charge aussi uniformément que possible entre plusieurs nœuds de stockage afin d’éviter des points chauds susceptibles de provoquer des problèmes de performance visibles, comme des pics de latence ou une baisse du nombre d’opérations par seconde
- On pourrait aussi appeler cela du load balancing, mais on réserve généralement le terme load balancer aux nœuds stateless
- Dans les systèmes stateful, des hotspots peuvent se former si des objets très demandés sont regroupés sur un nœud de stockage particulier, ce qui crée de la contention
- Un load balancer peut répartir uniformément la charge sur un ensemble de nœuds stateless avec des stratégies simples comme l’aléatoire, le minimum de connexions ou certaines variantes de FIFO, mais un système stateful doit router les requêtes vers les nœuds en fonction de l’emplacement des données
- Déplacer les données pour redistribuer la charge est généralement appelé rebalancing
- Le problème se complique encore du fait que la répartition de la charge peut évoluer dans le temps
- La distribution des données devient alors un processus dynamique, qui doit gérer aussi bien des pics de courte durée affectant de petits sous-ensembles de données que des variations de charge plus importantes dues à des cycles quotidiens ou à des événements saisonniers touchant plusieurs tenants
- Les grands ensembles de données, comme les grosses bases de données ou les flux d’événements à haut débit, doivent être shardés pour répartir efficacement la charge
- Le rebalancing devient alors un rebalancing des shards, et le système peut aussi scinder ou fusionner des shards à mesure que la distribution de la charge évolue
- Cependant, des compromis peuvent exister autour de la localité des données, notamment en lien avec le nombre et la taille des shards
- D’un côté, plus les données sont co-localisées, plus les recherches sont efficaces
- De l’autre, le coût des calculs qui doivent aller chercher des données dans trop de shards peut dépasser les bénéfices obtenus en répartissant la charge sur davantage de serveurs
- La gestion des hotspots peut aussi être nécessaire dans un système mono-tenant ; ce n’est donc pas un problème propre à la multi-tenancy
- Mais dans les systèmes de données MT, elle devient encore plus importante pour éviter que les tenants ne subissent des variations de qualité de service
Atteindre une forte utilisation des ressources
- L’une des principales motivations derrière l’architecture serverless multi-tenant est de fournir de meilleures performances économiques en utilisant plus efficacement les ressources matérielles sous-jacentes
- L’augmentation du taux d’utilisation grâce à la mutualisation des ressources est primordiale, mais l’obtenir tout en garantissant l’isolation des tenants et des performances prévisibles reste difficile
Cold start
- Les systèmes serverless qui peuvent réduire les ressources à zéro par tenant peuvent être confrontés au problème du cold start lorsque le tenant reprend sa charge de travail
- Le cold start est au cœur du serverless depuis l’origine, et il peut aussi affecter certains systèmes de données serverless
- Dans certains systèmes, il n’y a pas de cold start du tout ; dans d’autres, c’est une conséquence difficilement évitable de l’architecture et de l’offre de scale-to-zero
- Dans tous les cas que j’ai vus, le problème du cold start relève d’une décision produit, et le niveau de réduction des ressources peut varier selon le forfait et le modèle tarifaire
- En fin de compte, clients et fournisseurs peuvent choisir les compromis qui correspondent à leurs besoins respectifs
Systèmes étudiés
- Group 1 - Storage APIs (compute-light)
- Amazon DynamoDB (chapter 1)
- Kora - moteur Kafka serverless dans Confluent Cloud (chapter 2)
- Backblaze B2 (planned)
- Group 2 - SQL OLTP databases (compute-heavy)
- Neon - PostgreSQL serverless (chapter 3)
- Architecture multi-tenant serverless de CockroachDB. (in progress)
- PlanetScale (planned)
- Group 3 - SQL OLAP databases and data warehouses (compute-heavy)
- Google BigQuery (planned)
- ClickHouse Cloud (in progress).
- Ce travail va se poursuivre, avec un billet de « conclusion » prévu vers janvier/février 2024
Aucun commentaire pour le moment.