redis est une base de données, mais contrairement aux bases de données traditionnelles, les données Redis sont stockées en mémoire, donc la vitesse de lecture et d'écriture est très rapide, donc Redis est largement utilisé Direction du cache . memcached est un serveur de cache mémoire distribué hautes performances. L'objectif général de l'utilisation est d'augmenter la vitesse et l'évolutivité des applications Web dynamiques en mettant en cache les résultats des requêtes de base de données et en réduisant le nombre d'accès à la base de données.
L'auteur de Redis, Salvatore Sanfilippo, a comparé un jour ces deux systèmes de stockage de données basés sur la mémoire : # 🎜🎜#
Commandes communes : set/get/decr/incr/mget, etc.; #Scénarios d'application : la chaîne est le type de données le plus couramment utilisé, le stockage clé/valeur ordinaire peut être classé dans cette catégorie Méthode d'implémentation : la chaîne est stockée en interne dans Redis en tant que chaîne par défaut ; est référencé par redisObject. Lorsqu'il rencontre incr, decr, etc. Il sera converti en valeur numérique pour le calcul. À ce stade, le champ d'encodage de redisObject est int /hset/hgetall etc.
. Scénario d'application : nous souhaitons stocker des données d'objet d'informations utilisateur, notamment l'ID utilisateur, le nom d'utilisateur, l'âge et l'anniversaire. Grâce à l'ID utilisateur, nous espérons obtenir le nom, l'âge ou l'anniversaire de l'utilisateur ; : Le hachage de Redis stocke en fait la valeur en interne sous forme de HashMap et fournit une interface pour un accès direct à ce membre de la carte. Comme le montre la figure, la clé est l'ID utilisateur et la valeur est une clé de cette carte. le nom de l'attribut du membre, et la valeur est la valeur de l'attribut. De cette façon, les données peuvent être modifiées et accessibles directement via la clé de la carte interne (la clé de la carte interne est appelée champ dans Redis), c'est-à-dire. , via Key (ID utilisateur) + champ (étiquette d'attribut) peut exploiter les données d'attribut correspondantes. Il existe actuellement deux façons d'implémenter HashMap : lorsqu'il y a relativement peu de membres dans HashMap, Redis utilisera un tableau unidimensionnel pour le stocker de manière compacte. afin d'économiser de la mémoire, la vraie structure HashMap ne sera pas utilisée à ce moment-là, le codage du redisObject de la valeur correspondante est zipmap. Lorsque le nombre de membres augmente, il sera automatiquement converti en un vrai HashMap. l'encodage est ht. 🎜#3) Liste
Commandes courantes : lpush/rpush/lpop/rpop/lrange, etc.; Il existe de nombreux scénarios d'application pour la liste Redis. C'est également l'une des structures de données les plus importantes de Redis. Par exemple, la liste de suivi de Twitter, la liste de fans, etc. peuvent être implémentées en utilisant la structure de liste de Redis. méthode : la liste Redis est implémentée sous la forme d'une liste chaînée bidirectionnelle, c'est-à-dire qu'elle peut prendre en charge la recherche inversée et le parcours, ce qui est plus pratique à utiliser, mais cela entraîne également une surcharge de mémoire supplémentaire. De nombreuses implémentations dans Redis, y compris les files d'attente de tampon d'envoi, sont également mises en œuvre. utilisez cette structure de données.4) Set
Commandes communes : sadd/spop/smembers/sunion, etc.;Scénarios d'application : les fonctions externes fournies par Redis set sont similaires à celles de list. La particularité est que set peut éliminer automatiquement les doublons. Lorsque vous avez besoin de stocker une liste de données et que vous ne souhaitez pas que des données en double apparaissent, set est un. Un bon choix, et set fournit une interface importante pour juger si un certain membre est dans une collection set, ce que la liste ne peut pas fournir.
Méthode d'implémentation : l'implémentation interne de set est un HashMap dont la valeur est toujours nulle ; consiste à trier rapidement les doublons en calculant le hachage, c'est pourquoi set peut fournir un moyen de déterminer si un membre est dans l'ensemble.
5) Ensemble trié
Commandes communes : zadd/zrange/zrem/zcard, etc. ;
Scénarios d'application : Les scénarios d'utilisation de l'ensemble trié Redis sont similaires à set, la différence est que l'ensemble n'est pas automatiquement ordonné , tandis que l'ensemble trié peut Les membres sont triés en fournissant un paramètre de priorité (score) supplémentaire par l'utilisateur, et les membres sont triés par insertion, c'est-à-dire automatiquement triés. Lorsque vous avez besoin d'une set list ordonnée et non dupliquée, vous pouvez choisir une structure de données d'ensemble triée. Par exemple, la chronologie publique de Twitter peut être stockée avec l'heure de publication comme score, de sorte qu'elle soit automatiquement triée par heure lors de sa récupération.
Méthode d'implémentation : l'ensemble trié Redis utilise en interne HashMap et la liste de sauts (SkipList) pour garantir le stockage et l'ordre des données. HashMap stocke le mappage des membres aux scores, tandis que la liste de sauts stocke tous les membres, triés en fonction du score stocké dans. HashMap, utilisant la structure de table de saut, peut atteindre une efficacité de recherche plus élevée et est relativement simple à mettre en œuvre.
Dans Redis, toutes les données ne sont pas toujours stockées en mémoire. C'est la plus grande différence par rapport à Memcached. Lorsque la mémoire physique est épuisée, Redis peut échanger certaines valeurs qui n'ont pas été utilisées depuis longtemps sur le disque. Redis mettra uniquement en cache toutes les informations de clé. Si Redis constate que l'utilisation de la mémoire dépasse un certain seuil, l'opération d'échange sera déclenchée. Redis calcule quelles clés correspondent à la valeur requise en fonction de l'échange "swappability = age*log(size_in_memory)". disque. Ensuite, les valeurs correspondant à ces clés sont conservées sur le disque et effacées en mémoire. Cette fonctionnalité permet à Redis de conserver des données qui dépassent la taille de la mémoire de sa machine elle-même. Bien entendu, la capacité mémoire de la machine doit être suffisante pour stocker toutes les données clés, puisque ces données ne seront pas échangées. Dans le même temps, lorsque Redis échange les données de la mémoire sur le disque, le thread principal qui fournit le service et le sous-thread qui effectue l'opération d'échange partageront donc cette partie de la mémoire, si les données en ont besoin. être échangé est mis à jour, Redis bloquera l'opération jusqu'à ce que les modifications du sous-thread ne puissent être apportées qu'après avoir terminé l'opération d'échange. Lors de la lecture de données depuis Redis, si la valeur correspondant à la clé de lecture n'est pas dans la mémoire, Redis doit alors charger les données correspondantes à partir du fichier d'échange, puis les renvoyer au demandeur. Il y a ici un problème de pool de threads d’E/S. Par défaut, Redis bloquera, c'est-à-dire qu'il ne répondra pas tant que tous les fichiers d'échange ne seront pas chargés. Cette stratégie est plus adaptée lorsque le nombre de clients est faible et que des opérations par lots sont effectuées. Si vous souhaitez utiliser Redis dans une application de site Web à grande échelle avec une concurrence élevée, ce n'est évidemment pas suffisant pour répondre aux besoins. Ainsi, Redis nous exécute pour définir la taille du pool de threads d'E/S et effectuer des opérations simultanées sur les demandes de lecture qui doivent charger les données correspondantes à partir du fichier d'échange pour réduire le temps de blocage.
Pour les systèmes de bases de données basés sur la mémoire comme Redis et Memcached, l'efficacité de la gestion de la mémoire est un facteur clé affectant les performances du système. La fonction malloc/free dans le langage C traditionnel est la méthode la plus couramment utilisée pour allouer et libérer de la mémoire, mais cette méthode présente des défauts majeurs : premièrement, pour les développeurs, une incompatibilité entre malloc et free peut facilement provoquer des fuites de mémoire. une grande quantité de fragments de mémoire qui ne peuvent pas être recyclés et réutilisés, réduisant ainsi l'utilisation de la mémoire, enfin, en tant qu'appel système, sa surcharge système est bien supérieure à celle des appels de fonction ordinaires ; Par conséquent, afin d'améliorer l'efficacité de la gestion de la mémoire, les solutions de gestion de mémoire efficaces n'utiliseront pas directement les appels malloc/free. Redis et Memcached utilisent tous deux leurs propres mécanismes de gestion de la mémoire, mais leurs méthodes de mise en œuvre sont très différentes. Les mécanismes de gestion de la mémoire des deux seront présentés séparément ci-dessous.
Memcached utilise le mécanisme d'allocation de dalles par défaut pour gérer la mémoire. Son idée principale est de diviser la mémoire allouée en blocs de longueurs spécifiques en fonction de la taille prédéterminée pour stocker des enregistrements de données clé-valeur de longueurs correspondantes afin de résoudre complètement la mémoire. problème de fragmentation. Le mécanisme d'allocation de dalles est uniquement conçu pour stocker des données externes, ce qui signifie que toutes les données clé-valeur sont stockées dans le système d'allocation de dalles, tandis que les autres requêtes de mémoire pour Memcached sont demandées via malloc/free ordinaire, car le nombre de ces requêtes et La fréquence détermine qu'ils n'affecteront pas les performances de l'ensemble du système. Le principe de l'attribution des dalles est assez simple. Comme le montre la figure, il s'applique d'abord à un gros bloc de mémoire du système d'exploitation, le divise en morceaux de différentes tailles et divise les morceaux de même taille en groupes de classes de dalles. Chunk est utilisé comme la plus petite unité pour stocker les données clé-valeur. La taille de chaque classe Slab peut être contrôlée en spécifiant le facteur de croissance au démarrage de Memcached. Supposons que la valeur du facteur de croissance dans la figure est de 1,25. Si la taille du premier groupe de fragments est de 88 octets, la taille du deuxième groupe de fragments est de 112 octets, et ainsi de suite.
Lorsque Memcached reçoit les données envoyées par le client, il sélectionnera d'abord la classe Slab la plus appropriée en fonction de la taille des données reçues, puis interrogera la liste des morceaux libres dans la classe Slab enregistrée par Memcached Vous pouvez trouver un morceau qui peut être utilisé pour stocker des données. Lorsqu'une base de données expire ou est supprimée, le morceau dans lequel elle se trouve peut être recyclé et réajouté à la liste libre.
D'après le processus ci-dessus, nous pouvons voir que le système de gestion de la mémoire de Memcached est très efficace et ne provoquera pas de fragmentation de la mémoire, mais son plus grand inconvénient est qu'il entraîne un gaspillage d'espace. Les données de longueur variable ne peuvent pas utiliser pleinement la longueur spécifique de l'espace mémoire allouée à chaque morceau. Comme le montre la figure, 100 octets de données sont mis en cache dans un morceau de 128 octets et les 28 octets restants sont gaspillés.
La manière dont Redis implémente la gestion de la mémoire implique principalement les deux fichiers zmalloc.h et zmalloc.c dans le code source. Afin de faciliter la gestion de la mémoire, Redis va stocker la taille de cette mémoire dans la tête du bloc mémoire après avoir alloué un morceau de mémoire. real_ptr pointe vers le bloc de mémoire renvoyé après que Redis ait appelé malloc. Redis stocke la taille du bloc mémoire dans l'en-tête. La taille de la mémoire occupée par size est connue et correspond à la longueur du type size_t, puis renvoie ret_ptr. Lorsque de la mémoire doit être libérée, ret_ptr est transmis au gestionnaire de mémoire. Grâce à ret_ptr, le programme peut facilement calculer la valeur de real_ptr, puis transmettre real_ptr à free pour libérer de la mémoire.
Redis enregistre toutes les allocations de mémoire en définissant un tableau. La longueur de ce tableau est ZMALLOC_MAX_ALLOC_STAT. Chaque nombre représente le nombre de blocs de mémoire actuellement alloués par le programme, et la taille de chaque bloc de mémoire est égale à l'index du tableau dans lequel il se trouve. Dans le code source, ce tableau est zmalloc_allocations. zmalloc_allocations[16] représente le nombre de blocs de mémoire alloués d'une longueur de 16 octets. Il existe une variable statique used_memory dans zmalloc.c pour enregistrer la taille totale de la mémoire actuellement allouée. Par conséquent, en général, Redis utilise le package mallc/free, qui est beaucoup plus simple que la méthode de gestion de la mémoire de Memcached.
Bien que Redis soit un système de stockage basé sur la mémoire, il prend lui-même en charge la persistance des données en mémoire et fournit deux principaux types de stratégie de persistance : Instantané RDB et journal AOF. Memcached ne prend pas en charge les opérations de persistance des données.
1) Instantané RDB
L'instantané RDB est un mécanisme de persistance de Redis, qui permet aux utilisateurs de stocker l'instantané de données actuel en tant que document de données . Redis utilise le mécanisme de copie en écriture de la commande fork pour générer un instantané qui est écrit en continu dans la base de données. Lors de la génération d'un instantané, utilisez l'opération fork pour créer un processus enfant, parcourez toutes les données du processus enfant et écrivez-les dans le fichier RDB. Nous pouvons configurer le moment de la génération de l'instantané RDB via la commande save de Redis. Par exemple, nous pouvons configurer l'instantané pour qu'il soit généré après 10 minutes, ou nous pouvons le configurer pour générer un instantané après 1 000 écritures, ou nous pouvons implémenter plusieurs règles ensemble. La définition de ces règles se trouve dans le fichier de configuration Redis. Vous pouvez également définir les règles pendant l'exécution de Redis via la commande Redis CONFIG SET sans redémarrer Redis.
Le fichier RDB de Redis ne sera pas endommagé car son opération d'écriture est effectuée dans un nouveau processus. Lorsqu'un nouveau fichier RDB est généré, le sous-processus généré par Redis écrira d'abord les données dans un fichier RDB. fichier temporaire, le fichier temporaire est ensuite renommé en fichier RDB via l'appel système de renommage atomique, de sorte que si une panne se produit à tout moment, le fichier Redis RDB est toujours disponible. Dans l'implémentation interne de la synchronisation maître-esclave Redis, les fichiers RDB jouent également un rôle important. RDB a ses défauts, c'est-à-dire qu'en cas de problème avec la base de données, les données enregistrées dans notre fichier RDB ne sont pas toutes neuves. Toutes les données de la dernière génération de fichier RDB jusqu'à l'arrêt de Redis seront perdues. Dans certaines entreprises, cela est tolérable.
2) Journal AOF
Le nom complet du journal AOF est "Append Write File", qui est un fichier journal qui est continuellement ajouté et écrit. Différent du binlog des bases de données générales, les fichiers AOF sont du texte brut identifiable et leur contenu est constitué de commandes standard Redis une par une. Seules les commandes entraînant la modification des données seront ajoutées au fichier AOF. Chaque commande pour modifier les données génère un journal et le fichier AOF deviendra de plus en plus gros, donc Redis fournit une autre fonction appelée réécriture AOF. Sa fonction est de régénérer un fichier AOF. Il n'y aura qu'une seule opération sur un enregistrement dans le nouveau fichier AOF, contrairement à un ancien fichier qui peut enregistrer plusieurs opérations sur une même valeur. AOF est généré de la même manière que RDB, en bifurquant un processus, en parcourant directement les données et en les écrivant dans un nouveau fichier AOF temporaire. Pendant l'écriture des données dans le nouveau fichier, tous les journaux des opérations d'écriture seront toujours enregistrés dans le fichier AOF d'origine et seront enregistrés dans la mémoire tampon en même temps. Une fois les opérations importantes terminées, tous les journaux de tampon seront écrits dans des fichiers temporaires par lots. Ensuite, utilisez la commande atomique "rename" pour remplacer l'ancien fichier AOF par le nouveau fichier AOF.
AOF est une opération d'écriture de fichier. Son but est d'écrire le journal des opérations sur le disque, il rencontrera donc également le processus d'opération d'écriture que nous avons mentionné ci-dessus. Après avoir appelé write sur AOF dans Redis, utilisez l'option appendfsync pour contrôler le temps nécessaire pour appeler fsync pour l'écrire sur le disque. Le niveau de sécurité des trois paramètres de appendfsync ci-dessous devient progressivement renforcé. Non débogué. Dans la plupart des systèmes d'exploitation Linux, une opération fsync est effectuée toutes les 30 secondes pour écrire les données du tampon sur le disque.
appendfsync Everysec Lorsque appendfsync est défini sur Everysec, Redis effectuera un appel fsync par défaut toutes les secondes pour écrire les données du tampon sur le disque. Mais lorsque cet appel fsync dure plus d'une seconde. Redis adoptera la stratégie consistant à retarder fsync et attendra encore une seconde. C'est-à-dire que fsync sera exécuté après deux secondes. Cette fois, fsync sera exécuté quel que soit le temps d'exécution. L'opération d'écriture en cours sera bloquée car le descripteur de fichier sera bloqué pendant que l'opération fsync est en cours. Par conséquent, dans des circonstances normales, Redis effectuera une opération fsync toutes les secondes. Dans le pire des cas, une opération fsync se produit toutes les deux secondes. Cette opération est appelée validation de groupe dans la plupart des systèmes de bases de données. Elle combine les données de plusieurs opérations d'écriture et écrit le journal sur le disque en même temps.
appednfsync toujours Lorsque appendfsync est défini sur toujours, fsync sera appelé une fois pour chaque opération d'écriture. À ce stade, les données sont les plus sécurisées. fsync sera exécuté à chaque fois, ses performances seront donc également affectées.
Pour les besoins généraux de l'entreprise, il est recommandé d'utiliser RDB pour la persistance. La raison en est que la surcharge de RDB est bien inférieure à celle des journaux AOF. Je ne peux pas le supporter. Pour les applications de perte de données, il est recommandé d'utiliser les journaux AOF.
Memcached est un système de mise en mémoire tampon de données complète. Bien que Redis prenne en charge la persistance des données, la mémoire complète est après tout l'essence de ses hautes performances. . En tant que système de stockage basé sur la mémoire, la taille de la mémoire physique de la machine correspond à la quantité maximale de données que le système peut accueillir. Afin d'étendre les capacités de stockage, lorsque la quantité de données à traiter dépasse la limite de mémoire physique d'une seule machine, un cluster distribué doit être établi.
Par rapport à Memcached, qui ne peut utiliser le client que pour implémenter le stockage distribué, Redis préfère créer un stockage distribué côté serveur. La dernière version de Redis prend déjà en charge les fonctions de stockage distribué. Redis Cluster est une version avancée de Redis qui implémente la distribution et autorise des points de défaillance uniques. Il n'a pas de nœud central et a une évolutivité linéaire. La figure ci-dessous montre l'architecture de stockage distribuée de Redis Cluster, dans laquelle les nœuds communiquent entre eux via le protocole binaire, et entre les nœuds et les clients via le protocole ascii. En termes de stratégie de placement des données, Redis Cluster divise l'intégralité du champ de valeur de clé en 4 096 emplacements de hachage. Chaque nœud peut stocker un ou plusieurs emplacements de hachage, ce qui signifie que le nombre maximum actuel de nœuds pris en charge par Redis Cluster est de 4 096. L'algorithme distribué utilisé par Redis Cluster est également très simple : crc16(key) % HASH_SLOTS_NUMBER.
Redis Cluster introduit des nœuds maîtres et des nœuds esclaves pour garantir que les données sont toujours disponibles en cas de point de défaillance unique. Dans Redis Cluster, chaque nœud maître possède deux nœuds esclaves correspondants pour la redondance. De cette manière, dans l'ensemble du cluster, le temps d'arrêt de deux nœuds n'entraînera pas d'indisponibilité des données. Une fois le nœud maître hors ligne, le cluster sélectionne automatiquement un nouveau nœud maître parmi les nœuds esclaves.
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!