Meilleures pratiques: Windows Azure Tables & Queues
Tables
Les PartitionKey sont utilisées pour répartir les données de vos tables sur plusieurs serveurs.
L’on a alors les opérations habituelles, Create/Query/Delete sur les Tables, et Insert/Update/Delete/Query sur les entités.
Le SDK fournit un client complet pour accéder aux Tables, fondé sur ADO.NET (ou plutôt WCF) Data Services.
Il est critique de bien choisir les clefs (PartitionKey & RowKey). Il faut prendre en compte:
- Scalabilité: permettre à Azure de bien distribuer les partitions “chaudes”; il faut donc bien choisir la PartitionKey
- Efficacité des requêtes
- Transactions sur une partition entière: là encore le choix de la PartitionKey est critique
Plusieurs cas présentés pour les PartitionKey:
- PartitionKey statique, RowKey = titre du film
- Toutes les données iront sur un seul serveur; ce serveur devient donc un goulot d’étranglement
- PartitionKey = catégorie du film
- Le système peut détecter qu’un serveur devient surchargé et peut assigner une partie des partitions sur un autre serveur, dynamiquement
Deuxième cas: écriture intensive, on logue des transactions dans une table, récupérables par plages de temps
- Utiliser le Timestamp (heure) comme PartitionKey
- Problème: c’est toujours la denière partition qui sera “chaude” car c’est là que l’on ajoute les enregistrements
- Essayons d’ajouter un préfixe au timestamp, variable, comme un simple algorithme de hash
- Si l’on hashe les timestamp sur 20 blocs, on divise de fait les données dans 20 partitions
- Mais comment retrouver les entrées par timestamp maintenant que l’on a 20 préfixes
- l’on peut effectuer des requêtes parallèles sur les 20 partitions
Pour les RowKey:
Lorsque l’on acdède à une entité unique par PartitionKey/RowKey, le système trouve le serveur où se trouve la partition puis trouve l’entité correspondant à la RowKey. Dans ce cas, l’on n’a pas besoin de “continuation token”.
Maintenant, si l’on requête “select * from movies where rating>4”, l’on va scanner toute la table, renvoyer e.g. 1000 entités, plus un continuation token qui permet de reprendre la requête et de continuer de scanner la table. L’on peut avoir 0 résultats mais tout de même un continuation token, si l’on franchit une limite de partition sans trouver de résultats.
L’on peut accélérer ces requêtes en les divisant par partitions, e.g. “PartitionKey >= ‘A’ and PartitionKey <=’D’”… On peut alors exécuter les requêtes en parallèle.
Les requêtes peuvent être de plusieurs types en termes de performances:
- Rapide: PartitionKey & RowKey spécifiées
- Moyen: une seule partition, mais un espace de RowKey limité
- Lent:
- scans larges sur une table complète
- utilisation de prédicats “ou” dans la requête
- Dans tous las cas sauf le premier, l’on peut avoir des continuation tokens
- maximum de 1000 entités dans une réponse
Pour des requêtes liées à des interactions utilisateurs, utiliser un cache.
Entity Group Transactions: permettent de grouper un maximum de 100 commandes sur un ensemble d’entités réunies dans une même partition.
Queues
Les Queues permettent de délivrer des messages de façon fiable pour des traitements asynchrones. Les Queues contiennent des messages (<= 8 KB); l’on peut spécifier des dates d’expiration. L’on peut ajouter/supprimer des messages.
Les consommateurs de messages vont utiliser le DequeueCount pour identifier des messages qui pourraient poser problème: si un message est dépilé plusieurs fois mais revient dans la file, il provoque peut-être des plantages des workers par exemple. Il également important que le traitement du message soit idempotent (répétable) toujours pour le cas où des messages reviennent dans la file.
Le message count permet d’évaluer les besoins en puissance de traitement par rapport au nombre de messages en attente.
L’on peut typiquement utiliser les Blobs pour stocker des données, avec une référence dans le message. Penser à pouvoir effacer les Blobs qui deviendraient “orphelins”.
Futur: permettre aux Workers d’étendre le délai d’invisibilité, et des délais supérieurs pour les traitements longs.
Encore une fois, le SDK inclut une librairie client “officielle” (ce n’est plus un simple exemple).