Protections contre les défaillances

Hadoop et MapReduce en Java

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com
Dans les premiers articles théoriques on a vu que Hadoop était un système robuste et plutôt bien protégé contre toute sorte des défaillances. Maintenant on s'approchera de cet aspect important du système et présentera comment il se protège contre de différents soucis.

Parmi les mécanmismes de protection, le plus fameux est la réplication. C'est par elle qu'on commencera cet article. Ensuite on reviendra au concept des sous-tâches spéculatives. La troisième technique présentée sera le namenode secondaire. Dans la partie suivante on verra comment Hadoop s'assure que les données échangées sont correctes et complètes. Dans le dernier paragraphe on parlera des failles liées au MapReduce et des protections existantes.

Réplication dans Hadoop
Ce concept est au coeur de fonctionnement de Hadoop. La réplication consiste à dupliquer un élément dans un ou plusieurs endroits différents. Dans HDFS les blocks sont dupliqués. Grâce à cela, si le block d'une machine est indisponible, il pourra être aussi bien récupéré sur une autre machine.

Par défaut, les machines de réplication sont choisies de telle manière que même des scénarios les plus pessimistes ne devraient pas nuire au bon fonctionnement du système. Les copies sont stockées sur deux clusters différents (pour le cas du nombre de duplicatas par défaut : 3). Grâce à cela, on gagne de l'indépendance fonctionnelle par rapport à une entité de fonctionnement.

En plus, quand une machine tombe en panne, la valeur de réplication diminue de 1. Du coup on peut se retrouver avec 2 duplicatas au lieu de 3. Dans cette situation HDFS permet de revenir à l'état normal, c'est-à-dire 3 duplicatas. Quand le système rencontre un block défaillant (absent, incomplet), namenode marque ce block en état "anomalie". Ensuite le namenode programme la copie du même block, mais dont l'état est "normal", sur une autre machine. Quand la copie a lieu, le block défaillant est supprimé.

Intégrité des données
L'intégrité des données est garantie par le mécanisme de checksum. Au moment d'écriture des données, HDFS génère une "clé de vérification", connu sous le nom de checksum. Quand un client tente de lire les données, le système vérifie le checksum des informations qui sont retournées.

En plus de cette action en temps réel, chaque datanode fait tourner un scanneur qui vérifie la conformité de tous les blocks sauvegardés. Ce scanneur est un thread lancé périodiquement, à l'intervalle régulière. Elle est définie dans la propriété de configuration dfs.datanode.scan.period.hours. Le rapport de cette analyse est disponible sur l'interface web du datanode, sous l'adresse ${datanode}/blockScannerReport.

Namenode secondaire
Le namenode principal n'est pas une divinité protégée contre tous les problèmes potentiels que peut subir une machine. Il peut également tomber en panne, sans pour autant d'exposer le système au danger. Tout cela grâce au secondary namenode (namenode secondaire) qui permet d'effectuer une restauration des données à partir d'un point précis du passé.

Contrairement au namenode principal, le namenode secondaire n'enregistre aucune donnée. A la place de cela, il requête le namenode principal aux intervalles spécifiées dans la configuration, et récupère les images du système. Après, quand un problème est détecté avec le namenode principal, la restauration s'effectue à partir des documents enregistrés pendant les vérifications ponctuelles. Vu que le namenode secondaire a les mêmes exigeances en mémoire que le namenode principal, il ne devrait pas tourner sur la même machine. Et la faille des deux namenodes est moins probable que la faille du principal.

Le point négatif de restauration par le namenode secondaire, est une incohérence possible des données. On peut imaginer qu'il récupère l'image du système toutes les 3 heures. Beaucoup de choses peuvent se passer dans le système pendant ce laps de temps. Ces choses-là ne pourront pas être reprises par secondary namenode pendant la restauration.

Sous-tâches spéculatives
Il s'agit ici plutôt d'une méthode de protection contre une anomalie que contre un dysfonctionnement. MapReduce contient une liste des sous-tâches qui ensemble composent une tâche à effectuer. Dès qu'une de ces sous-tâches commence à répondre trop lentement, Hadoop entre en jeu avec ses speculative tasks (sous-tâches spéculatives).

En gros, une sous-tâche spéculative reprend exactement la tâche qui fonctionne lentement. Elle est lancée après le démarrage de toutes les sous-tâches. Elle s'applique seulement à celles dont la moyenne de progression est beaucoup plus petite que la moyenne des autres sous-tâches.

Même si les mêmes sous-tâches peuvent tourner en un temps donné, elles ne vont jamais produire deux résultats. Si la sous-tâche d'origine, malgré les problèmes initiaux, s'exécute avant la sous-tâche spéculative, son résultat est pris en compte. Quant à la situation inverse, le résultat de sous-tâche spéculative est pris en compte.

Défaillances potentielles pendant MapReduce
Les sous-tâches spéculative ne sont pas la seule solution aux problèmes potentiels du MapReduce. Un autre mécanisme se base sur la propriété mapred.task.timeout qui indique le timeout d'exécution d'une sous-tâche. Dès que jobtracker ne reçoit pas une notification de la part du tasktracker au bout de ce temps, il considère la sous-tâche comme défaillante. La JVM de la sous-tâche est alors tuée et la sous-tâche en question reprogrammée. Jobtracker essaie toujours de reprogrammer la sous-tâche sur la machine différente de la dernière pour rendre l'exécution possible. Le nombre de reprogrammations peut être contrôlé avec la propriété de configuration mapred.map.max.attempts ou mapred.reduce.max.attempts, respectivement pour les tâches map et reduce.

La faille du jobtracker est un problème plus sérieux car il s'agit d'un point qui gère des sous-tâches. Il est très lié aux problèmes avec la machine et une des protections s'appelle ZooKeeper. Cette protection est un service de coordination destinée à des systèmes distribués. Les buts de ce service sont :
- coordination de plusieurs processus distribués à travers un namespace (espace de nom) partagé, tout comme dans un système de fichier standard. Cette coordination peut se faire grâce aux znodes qui représentent la même chose que les fichiers et les répertoires. La seule différence est qu'ils ne stockent pas de données sur le disque, mais dans la mémoire. Le stockagen n'est donc pas persitant.
- réplication à travers les groupes de fichiers qui garantit une meilleure protection contre une défaillance unitaire dans la chaîne.
- atomicité qui revient à la notion de transaction SQL. Aucun résultat partiel d'une opération n'est admis dans ZooKeeper. On effectue toutes les tâches correctement ou aucune.
- séquentialité qui garantit que toutes les opérations vont s'appliquer dans l'ordre d'envoi.
- partage de ressource grâce auquel le client verra toujours la même chose, indépendamment de la machine qui fournit les données.
- synchronisation qui permet de garder les mêmes données sur toutes les machines concernées par une opération.

Quasiment tous les points Hadoop sont protégés contre les défaillances. La réplication apparaît ici un moyen évident. Surtout quand on a plusieurs clusters composés de plusieurs machines. Mais il y a aussi des méthodes moins évidentes, comme les tâches spéculatives ou la restitution automatique des données. La restitution peut également être manuelle, mais elle doit tenir compte du volume des données. Il provoquera obligatoirement un devoir de prioriser les données à sauvegarder.
Bartosz KONIECZNY 08-09-2013 16:06 Hadoop
Moi

Développeur d'applications Internet et journaliste passionné par l'adjectif français. Un aigle polonais orienté vers la progression, volant très haut et écoutant du zouk après les matches du foot français.

Vous appréciez mon travail ?

Pour contribuer au développement de ce site, ou pour remercier pour des articles rédigés, vous pouvez faire un don.

Un conseil PHP

Comment créer une signature pour OAuth

La création d'une signature (paramètre oauth_signature) pour la requête OAuth est réalisée avec l'algorithme HMAC-SHA1. Son implémentation chez PHP se présente ainsi :

hash_hmac('sha1', "Message to hashed", "Secret key", true)
Le résultat de cet algorithme doit ensuite être encodé avec Base64. Un exemple d'utilisation chez le protocle OAuth peut se présenter de la manière suivante :
public function getSignature($baseString, $signatureKey)
{
  return base64_encode(hash_hmac('sha1', $baseString, $signatureKey, true));   
}