Présentation | Nous avons présenté la naissance du pika, les caractéristiques du pika, le noyau du pika et l'utilisation du pika dans "Stockage Redis de grande capacité - Tout sur le pika". L'article analyse en détail les fichiers importants dans la logique de synchronisation pika : la méthode de stockage des données et le principe de mise en œuvre de « write2file », qui vaut vraiment la peine d'être lu ! |
pika est un stockage de grande capacité de type Redis développé conjointement par le DBA du département Plateforme Web 360 et l'équipe d'infrastructure. L'émergence de pika ne vise pas à remplacer Redis, mais à compléter les scénarios Redis. Pika s'efforce de résoudre les problèmes de Redis dans des scénarios de grande capacité grâce à un stockage persistant en partant du principe qu'il est entièrement compatible avec le protocole Redis et qu'il hérite de la conception pratique d'exploitation et de maintenance de Redis, comme un temps de récupération lent, un coût élevé de maître-esclave. synchronisation, thread unique relativement fragile et capacité de charge les données sont limitées, le coût de la mémoire est élevé, etc.
binlog du principe de réplication maître-esclave de PikaLes fichiers liés à Binlog contiennent deux parties : manifest et write2file. Le manifeste enregistre les méta-informations du journal, y compris le numéro de fichier journal actuel et le décalage actuel du fichier journal write2file+num enregistre toutes les commandes et paramètres d'écriture redis reçus par pika.
Format de fichierFormat du fichier manifeste :
Décalage du journal (8 octets)|con_offset (8 octets, inutilisés)|Nombre d'éléments (4 octets, inutilisés)|Numéro du fichier journal (4 octets).
Format du fichier Binlog :
La taille fixe du fichier Binlog est de 100 Mo. Chaque fichier Binlog est composé de plusieurs blocs. La taille de chaque bloc est fixée à 64 Ko. Chaque commande d'écriture redis est appelée un enregistrement. Un enregistrement peut être distribué dans plusieurs blocs, mais il ne sera distribué que dans un seul fichier Binlog, le fichier Binlog peut donc dépasser 100 Mo.
Format d'enregistrement : En-tête|Cmd
En-tête : longueur de l'enregistrement (3 octets) | Horodatage (4 octets) | Type d'enregistrement (1 octet).
Cmd : une partie ou la totalité de la commande redis, selon que l'espace restant du bloc actuel peut stocker le Record.
Cours de mise en œuvreCours de base
Version : classe de méta-informations, mappée via des fichiers mmap et manifeste.
Binlog : classe de journal, mappée via les fichiers mmap et write2file.
PikaBinlogSenderThread : classe de consommation de journaux, lit séquentiellement le contenu du fichier journal et consomme les journaux.
Opérations de baseConstruire Binlog
//file_size peut être spécifié dans le fichier de configuration, la valeur par défaut est 100 Mo
Binlog::Binlog(const std::string& binlog_path, const int file_size)
1.1 Créer un répertoire de fichiers binlog.
1.2 Vérifiez si le fichier manifeste dans le répertoire des journaux existe. S'il n'existe pas, créez-en un nouveau.
1.3 Initialisez la classe Version en fonction du fichier manifeste.
1.4 Recherchez le fichier journal correspondant en fonction du numéro de fichier dans le manifeste, localisez la position d'ajout du fichier en fonction de pro_offset, initialisez le pointeur de journal, enregistrez la longueur du contenu du journal et le nombre de blocs de bloc.
Mettre à jour l'état actuel de la production de grumes
//pro_num : numéro de fichier journal
//pro_offset : décalage du fichier journal
//Utilisé pour mettre à jour les informations du binlog correspondant à l'instance esclave lorsqu'une synchronisation complète est requise
Status Binlog :: SetProducerStatus (uint32_t pro_num, uint64_t pro_offset)
2.1 Supprimez write2file0.
2.2 Supprimez write2file+pro_num.
2.3 Construisez un nouveau fichier write2file+pro_num, remplissez les espaces pro_offset, initialisez version->pro_num à pro_num, version->pro_offset à pro_offset et actualisez-le dans le fichier manifeste.
2.4 Initialisez la taille du fichier actuelle et block_offset.
Mettre à jour l'état actuel de la production de grumes
//filenum : numéro de journal actuel
//pro_offset : décalage actuel du journal
Status Binlog ::GetProducerStatus(uint32_t* filenum, uint64_t* pro_offset)
3.1 Lisez pro_num et pro_offset dans la version et renvoyez-les.
Journal de production
//Put->Produce->EmitPhysicalRecord
Status Binlog :: Put (const std :: string &item)
4.1 Vérifiez si le fichier journal actuel répond aux conditions de coupe, et si oui, coupez-le.
4.1.1 pro_num augmente de 1 et initialise les nouveaux fichiers journaux, version->pro_num=pro_num, version->pro_offset = 0, binlog->filesize = 0, binlog->block_offset = 0.
4.1.2 Si la taille restante du bloc actuel est 4.1.3 Produce est une boucle qui garantit que lorsque la taille de l'élément dépasse kBlockSize, plusieurs EmitPhysicalRecord peuvent être effectués pour compléter toutes les données de l'élément tombant dans le fichier binlog. La condition pour que la boucle se termine normalement est left==0. 4.1.3.1 Si left 4.1.3.2 Si laissé > disponible, cela signifie que plusieurs blocs sont nécessaires pour stocker les éléments, puis Type=kFirstType pour la première fois et EmitPhysicalRecord est appelé plusieurs fois. 4.1.3.3 S'il reste > disponible et que ce n'est pas la première fois que vous utilisez EmitPhysicalRecord, alors Type=kMiddleType, appelez EmitPhysicalRecord plusieurs fois. 4.1.4Émettre un enregistrement physique. 4.1.4.1 Splice RecordHeader (longueur de 3 octets + temps de 4 octets + type de 1 octet), écrire des données et mettre à jour block_offset et pro_offset. Journal de consommation //scratch : Le résultat de la consommation renvoie un cmd redis complet //Consume->ReadPhysicalRecord, ReadPhysicalRecord lit un enregistrement complet à chaque fois, plusieurs enregistrements constituent un cmd redis complet Status PikaBinlogSenderThread :: Consume (std :: string & scratch) 5.1Consume est une boucle, qui peut appeler ReadPhysicalRecord plusieurs fois. La condition de sortie de la boucle est que la lecture record_type==kFullType ou record_type==kLastType. 5.1.1 Si la lecture kBlockSize-last_record_offset_ <= kHeaderSize signifie que la fin du bloc a été lue et qu'elle est remplie de données, ignorez-la. 5.1.2 Lire les données, mettre à jour last_record_offset_, con_offset. Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!