Table des matières
1. Créez un cluster Redis basé sur Docker et DockerCompose
1.3. Exécutez le script shell et créez le fichier de configuration du cluster
1.4. Écrivez le fichier docker-compose.yml
1.8. Que dois-je faire si un nœud du cluster tombe en panne ?
2. Défaillance du cluster et traitement de l'expansion
2.1. Gestion des erreurs de cluster
b) Ajouter le nouveau nœud maître 110 au cluster
c) Réaffecter les emplacements
1. Créez un cluster Redis basé sur Docker et DockerCompose
1.1. Préface
Au stade actuel, comme je n'ai qu'un seul serveur cloud, il est plus difficile de construire un système distribué. Dans le travail réel, les clusters sont généralement construits à l'aide de plusieurs hôtes.
Je vais donc ici construire un cluster Redis basé sur Docker et Docker-compose (orchestration de conteneurs).
Ps : Avant la configuration, assurez-vous d'arrêter le conteneur Redis précédemment démarré.
1.2. Écrire un script shell
Sous Linux, les fichiers avec le suffixe .sh sont appelés "scripts shell". Grâce à ce fichier, nous pouvons exécuter par lots des instructions qui sont habituellement exécutées sous Linux. En même temps, nous pouvons également ajouter des conditions, des boucles, des fonctions et d'autres mécanismes. .
Ici, nous créons 11 nœuds Redis. Le contenu de ces fichiers de configuration Redis est similaire, nous utilisons donc un script pour les générer par lots (vous pouvez également les modifier un par un manuellement sans utiliser de script).
for port in $(seq 1 9); \
do \
mkdir -p redis${port}/
touch redis${port}/redis.conf
cat << EOF > redis${port}/redis.conf
port 6379
bind 0.0.0.0
protected-mode no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.30.0.10${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
EOF
done
# 注意 cluster-announce-ip 的值有变化,和上面分开写也是因为这个原因
for port in $(seq 10 11); \
do \
mkdir -p redis${port}/
touch redis${port}/redis.conf
cat << EOF > redis${port}/redis.conf
port 6379
bind 0.0.0.0
protected-mode no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 172.30.0.1${port}
cluster-announce-port 6379
cluster-announce-bus-port 16379
EOF
done
for port in $(seq 1 9) : représente une boucle, seq est une commande Linux, génère des nombres [1, 9] et les affecte à leur tour au port variable.
do, done : dans le shell, { } est utilisé pour représenter des variables, pas des blocs de code. Car for, do et done sont utilisés pour représenter le début et la fin d'un bloc de code (c'est ainsi que les langages de programmation des temps anciens étaient utilisés ).
\ : indique le caractère de suite, ce qui signifie fusionner le contenu de la ligne suivante et de la ligne actuelle en une seule ligne. Par défaut, le shell exige que tous les codes soient écrits sur une seule ligne, mais vous pouvez utiliser le caractère de suite pour rompre la ligne. et continuez à ajouter.
Le contenu du corps de la première boucle (le corps de la deuxième boucle a la même idée) : créez 9 dossiers nommés redis1, redis2, redis3... via mkdir, puis touchez redis${port} Sous chaque dossier, créez un redis.conf Le contenu du fichier (commençant par EOF et se terminant par EOF) est écrit dans chaque fichier redis.conf via cat.
Épissage de chaînes : dans le shell, l'épissage de chaînes est écrit directement ensemble, sans utiliser +.
cluster-enabled oui : activer le cluster
cluster-config-file : une fois le nœud démarré, le fichier de configuration du nœud généré automatiquement configurera certaines informations du cluster Redis.
cluster-node-timeout 5000 : le délai d'expiration du paquet de pulsation est défini sur 5 000 ms.
cluster-announce-ip : indique l'adresse IP de l'hôte où se trouve le nœud Redis actuel (actuellement, il s'agit d'un hôte simulé à l'aide d'un conteneur Docker, il doit donc s'agir de l'adresse IP du conteneur Docker).
cluster-announce-port : indique le port lié au nœud Redis actuel lui-même (le port dans le conteneur). Différents conteneurs peuvent avoir le même port à l'intérieur. Le mappage de port ultérieur est effectué, puis les différents ports à l'extérieur du conteneur sont mappés à les ports à l’intérieur du conteneur.
cluster-announce-bus-port : un serveur peut être lié à plusieurs numéros de port. Actuellement, cela représente le port de gestion (le port professionnel mentionné ci-dessus est utilisé pour la communication des données professionnelles), qui est utilisé pour effectuer certaines tâches de gestion. Communication (si le nœud maître Redis d'un certain fragment raccroche, le nœud esclave doit devenir le nœud maître, et cela doit être fait via le port de gestion).
1.3. Exécutez le script shell et créez le fichier de configuration du cluster
Exécutez le script shell via la commande suivante
Centos exécute la commande de script shell :
sh generate.sh
Ubuntu exécute la commande du script shell :
bash generate.sh
Après l'exécution, vous obtiendrez 11 répertoires, chaque répertoire possède un fichier de configuration et les adresses IP dans les fichiers de configuration sont différentes.
1.4. Écrivez le fichier docker-compose.yml
Dans le fichier de configuration, vous devez d'abord créer manuellement le réseau réseaux, puis attribuer le segment de réseau à l'adresse IP statique de chaque nœud lors de la création ultérieure du cluster Redis.
Ps : L'IP statique (IP fixe) est configurée ici pour une observation ultérieure.
version: '3.3'
networks:
mynet:
ipam:
config:
- subnet: 172.30.0.0/24
Créez ensuite chaque nœud dans le cluster Redis
services:
redis1:
image: 'redis:5.0.9'
container_name: redis1
restart: always
volumes:
- ./redis1/:/etc/redis/
ports:
- 6371:6379
- 16371:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.101
redis2:
image: 'redis:5.0.9'
container_name: redis2
restart: always
volumes:
- ./redis2/:/etc/redis/
ports:
- 6372:6379
- 16372:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.102
redis3:
image: 'redis:5.0.9'
container_name: redis3
restart: always
volumes:
- ./redis3/:/etc/redis/
ports:
- 6373:6379
- 16373:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.103
redis4:
image: 'redis:5.0.9'
container_name: redis4
restart: always
volumes:
- ./redis4/:/etc/redis/
ports:
- 6374:6379
- 16374:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.104
redis5:
image: 'redis:5.0.9'
container_name: redis5
restart: always
volumes:
- ./redis5/:/etc/redis/
ports:
- 6375:6379
- 16375:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.105
redis6:
image: 'redis:5.0.9'
container_name: redis6
restart: always
volumes:
- ./redis6/:/etc/redis/
ports:
- 6376:6379
- 16376:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.106
redis7:
image: 'redis:5.0.9'
container_name: redis7
restart: always
volumes:
- ./redis7/:/etc/redis/
ports:
- 6377:6379
- 16377:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.107
redis8:
image: 'redis:5.0.9'
container_name: redis8
restart: always
volumes:
- ./redis8/:/etc/redis/
ports:
- 6378:6379
- 16378:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.108
redis9:
image: 'redis:5.0.9'
container_name: redis9
restart: always
volumes:
- ./redis9/:/etc/redis/
ports:
- 6379:6379
- 16379:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.109
redis10:
image: 'redis:5.0.9'
container_name: redis10
restart: always
volumes:
- ./redis10/:/etc/redis/
ports:
- 6380:6379
- 16380:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.110
redis11:
image: 'redis:5.0.9'
container_name: redis11
restart: always
volumes:
- ./redis11/:/etc/redis/
ports:
- 6381:6379
- 16381:16379
command:
redis-server /etc/redis/redis.conf
networks:
mynet:
ipv4_address: 172.30.0.111
- sous-réseau : 172.30.0.0/24 : ici 172.30.0 est le numéro de réseau et l'adresse IP est l'adresse IP du réseau interne. Cela nécessite qu'il ne puisse pas entrer en conflit avec d'autres segments de réseau existants sur votre hôte actuel (le segment de réseau existant de chacun sur l'hôte ), les détails peuvent ne pas être les mêmes).
ipv4_address : 172.30.0.101 : configurez l'adresse IP statique ici. Notez que la partie numéro de réseau doit être cohérente avec le réseau précédent. La partie numéro d'hôte peut être configurée arbitrairement entre 1 et 255, à condition de ne pas la répéter. Cependant, nous devons ici correspondre à l'adresse IP d'annonce du cluster écrite dans le fichier de configuration avant.on, comme indiqué ci-dessous
1.5. Démarrez le conteneur
Démarrez tous les conteneurs configurés dans yml via docker-compose up -d.
1.6. Créer un cluster
Ici, les 9 premiers hôtes sont intégrés dans un cluster, 3 maîtres et 6 esclaves. Les 2 derniers hôtes sont temporairement inutilisés.
Construisez-le simplement avec la commande suivante
redis-cli --cluster create 172.30.0.101:6379 172.30.0.102:6379 172.30.0.103:6379 172.30.0.104:6379 172.30.0.105:6379 172.30.0.106:6379 172.30.0.107:6379 172.30.0.108:6379 172.30.0.109:6379 --cluster-replicas 2
--cluster create : Indique la création d'un cluster. Remplissez l'IP et l'adresse de chaque nœud (assurez-vous que l'IP de cette commande est cohérente avec l'environnement réel).
--cluster-replicas 2 : indique que chaque nœud maître nécessite deux sauvegardes de nœuds esclaves. Une fois cette configuration définie, Redis saura que 3 nœuds sont dans un groupe (sur un fragment), un total de 9 nœuds, un total de 3 fragments.
Après avoir entré oui, comme suit
1.7. Utiliser des clusters
Il y a maintenant neuf nœuds de 101 à 109, ce qui est un cluster. Utiliser un client pour se connecter à n'importe quel nœud est essentiellement équivalent (chaque cluster stocke une partie des données « ensemble complet », et lors de la connexion à n'importe quel client avec le -c option, l’ensemble des données est accessible ).
Après avoir établi le cluster, vous pouvez vous connecter au client via -h -p, -h ou vous connecter directement au port externe via -p, comme suit (les éléments suivants sont tous connectés à 172.30.0.103:6379) :
Affichez les informations actuelles du cluster via les nœuds du cluster.
Stocker les données dans le cluster
La raison de l'erreur dans l'image ci-dessus est qu'après le calcul de hachage de la clé k1, l'emplacement est 12706. Ce numéro d'emplacement appartient au fragment n°3 dans les informations de cluster que nous venons de visualiser.
Le message d'erreur nous invite à transmettre la demande du client au nœud 103.
Cela ne serait-il pas gênant ?
En fait, nous pouvons ajouter l'option -c lors du démarrage de redis-cli. À ce stade, le client redis trouvera automatiquement l'hôte de fragment correspondant en fonction du numéro d'emplacement calculé par la clé actuelle et terminera l'opération.
Faites attention à l'image ci-dessus.Après la redirection, le client connecté à redis changera également.
De plus, si vous essayez d'écrire des opérations sur le nœud esclave, celui-ci sera également automatiquement redirigé vers le nœud maître spécifié.
Ps : En fait, les commandes liées à Redis mentionnées précédemment sont fondamentalement applicables (à l'exception de quelques-unes, comme mset, mget... qui peuvent actionner plusieurs clés, ne sont pas disponibles. Car les clés peuvent être dispersées sur différents fragments).
1.8. Que dois-je faire si un nœud du cluster tombe en panne ?
Que se passe-t-il si le nœud en panne est un nœud esclave ? C'est bon ~
Que se passe-t-il si le nœud principal plante ? L'opération d'écriture ne peut pas être effectuée ! A ce stade, le travail effectué par le cluster est quelque peu similaire à celui effectué par la sentinelle : il sélectionnera automatiquement l'un des nœuds esclaves sous le nœud maître et le promouvra au nœud maître.
Ici, je laisse le nœud principal redis1 raccrocher.
docker stop redis1
Avant que redis1 ne raccroche, les informations sur le cluster sont les suivantes :
Une fois Redis1 raccroché, les informations sur le cluster sont les suivantes :
On peut voir que le mécanisme de cluster peut également gérer le basculement.
2. Défaillance du cluster et traitement de l'expansion
2.1. Gestion des erreurs de cluster
a) Détermination des défauts
1. Chaque nœud, chaque seconde, enverra des paquets ping à certains nœuds aléatoires (cela inclut des informations de configuration du cluster, telles que l'ID, à quel fragment il appartient, s'il s'agit d'un nœud maître ou d'un nœud esclave, et quels emplacements il détient. . ....), le nœud reçu renverra un paquet pong. Les paquets ping ici ne sont pas tous envoyés une seule fois. Ce paramètre permet d'éviter que lorsqu'il y a beaucoup de nœuds, il y ait aussi beaucoup de paquets de battement de cœur, ce qui consomme sérieusement bande passante du réseau.
2. Lorsque le nœud A envoie un paquet ping au nœud B et que B ne peut pas répondre comme prévu, A réinitialisera la connexion TCP avec B. Si la reconnexion échoue, A définira B sur PFAIL (équivalent à un mode hors ligne subjectif).
3. Une fois que A a déterminé que B est PFAIL, il communiquera avec d'autres nœuds via le protocole Gossip intégré de redis et confirmera l'état de B avec d'autres nœuds.
4. Si A constate qu'il existe de nombreux autres nœuds qui pensent également que B est PFAIL et que le nombre dépasse le nombre de clusters, alors A marquera B comme FAIL (équivalent à l'objectif hors ligne) et synchronisera ce message avec d'autres nœuds. d'autres nœuds marquent également B comme FAIL.
b) Basculement
Il y aura d’abord un jugement :
- Si B est un nœud esclave, aucun basculement n’est nécessaire.
- Si B est le nœud maître, alors les nœuds esclaves de B (tels que C et D) déclencheront le basculement.
béton:
1. Le nœud esclave détermine s'il est qualifié pour participer à l'élection. Si le nœud esclave n'a pas communiqué trop longtemps avec le nœud maître (pas de synchronisation des données pendant trop longtemps, la différence est trop grande), il perdra la qualification. courir.
2. Les nœuds qualifiés, tels que C et D, vont d'abord dormir pendant une certaine période. Temps de sommeil = 500 ms de temps de base + [0, 500 ms] temps aléatoire + classement * 1 000 ms. Plus la valeur de décalage est grande (indiquant que les données est plus proche du nœud maître) ), plus le classement est élevé (plus le temps de sommeil est court), c'est-à-dire que le temps de sommeil dépend principalement du classement .
3. Si le temps de sommeil de C est écoulé à ce moment-là, C sollicitera les votes pour tous les nœuds du cluster, mais seul le nœud maître est éligible pour voter (celui qui a un temps de sommeil plus court sera probablement le nouveau nœud maître).
4. Le nœud maître votera pour C (chaque nœud maître n'a qu'une seule voix). Lorsque le nombre de votes reçus par C dépasse la moitié du nombre de nœuds maîtres, C sera promu pour devenir le nœud maître (C n'exécute aucun esclave). un par lui-même, et laissez D exécuter slaveof C).
5. Dans le même temps, C synchronisera également l'information selon laquelle il est devenu le nœud maître avec les autres nœuds du cluster, et chacun mettra à jour ses informations enregistrées sur la structure du cluster.
6. Enfin, si le point hôte précédemment arrêté est restauré, il deviendra un nœud esclave et connecté au cluster.
2.2. Temps d'arrêt du cluster
Un temps d'arrêt du cluster se produira dans les trois situations suivantes :
Pour une certaine partition, tous les nœuds maîtres et esclaves sont en panne. À ce stade, la partition ne peut pas fournir de services de données.
Pour une certaine partition, le nœud maître est en panne, mais il n'y a pas de nœuds esclaves et les services de données ne peuvent pas être fournis.
Si plus de la moitié des nœuds maîtres sont en panne, cela signifie que le cluster a rencontré une situation très grave, et il faut s'arrêter et vérifier s'il y a un problème !
Ps : Si un nœud du cluster est en panne, quel que soit le nœud dont il s'agit, nos programmeurs doivent le gérer dans les plus brefs délais (au plus tard, il doit être traité avant d'aller travailler le lendemain).
2.3. Expansion du cluster
a) Analyse
Les opérations ci-dessus ont combiné 101 à 109 9 hôtes dans un cluster avec 3 maîtres et 6 esclaves.
Ensuite, afin de démontrer l'expansion, 110 et 111 sont également ajoutés au cluster.
Prenez 110 comme maître et 111 comme esclave et divisez les données de 3 -> 4.
b) Ajouter le nouveau nœud maître 110 au cluster
redis-cli --cluster add-node 172.30.0.110:6379 172.30.0.101:6379
add-node : la première adresse IP et le numéro de port indiquent le nouveau nœud, et les deuxièmes numéros IP et de port indiquent n'importe quel nœud du cluster (n'importe lequel fera l'affaire, tant qu'il s'agit d'un nœud dans un cluster que vous souhaitez rejoindre) ( c'est tout), indiquant à quel cluster le nouveau nœud doit être ajouté.
Ensuite, vous pouvez voir à travers les nœuds du cluster que le nœud maître redis10 a rejoint le cluster, mais que les emplacements ne sont pas attribués.
c) Réaffecter les emplacements
Retirez les emplacements des trois ensembles de maîtres précédents et attribuez-les au nouveau maître.
redis-cli --cluster reshard 172.30.0.101:6379
Après avoir entré la commande, l'état de chaque machine du cluster actuel sera imprimé, puis il sera demandé à l'utilisateur de saisir le nombre d'emplacements à diviser.
Il y a 4 fragments, soit un total de 16 384. Divisez par 4 pour obtenir 4 096, remplissez donc simplement 4 096 ici (4 096 numéros d'emplacement sont divisés en redis10).
Immédiatement après, il vous demandera quel nœud recevoir, collez simplement l'identifiant de l'hôte redis10.
Ensuite, laissez-vous choisir à partir de quels nœuds vous souhaitez créer des emplacements :
- all : signifie cliquer sur tous les autres emplacements maîtres.
- Spécifiez manuellement de déplacer les emplacements d'un ou plusieurs nœuds (en terminant par terminé).
Après avoir tout saisi, le transport proprement dit ne sera pas effectué, mais le plan de transport sera donné en premier.
Après avoir entré oui, le transfert commence réellement. A ce moment, non seulement les slots sont re-divisés, mais les données correspondantes sur les slots seront également transférées vers le nouvel hôte. (C'est une opération relativement lourde)
d) Ajouter des nœuds esclaves au nouveau nœud maître
redis-cli --cluster add-node 172.30.0.111:6379 172.30.0.101:6379 --cluster-slave
Une fois l'exécution terminée, le nœud esclave a été ajouté.
Question : Le client peut-il accéder au cluster Redis pendant le processus de déplacement des emplacements/clés ?
Nous avons déjà entendu parler de l'algorithme de partitionnement des emplacements de hachage et nous pouvons savoir que la plupart des clés n'ont pas besoin d'être déplacées. Pour ces clés qui n'ont pas été déplacées, elles sont accessibles normalement à ce moment. Pour les clés qui sont en cours de déplacement, des erreurs d' accès peuvent survenir .
Supposons que le client accède à k1 et que le k1 obtenu par le cluster via l'algorithme de partitionnement soit les données du premier fragment, et qu'il sera redirigé vers le nœud du premier fragment. Il est alors possible qu'après la redirection, k1 Une fois déplacé, il deviendra naturellement inaccessible.
Si vous souhaitez étendre la capacité d'un environnement de production, vous devez quand même prendre votre temps. Par exemple, trouver un moment pour vous développer en pleine nuit lorsqu'aucun client n'accède au cluster, afin de minimiser la perte.
Évidemment, si vous souhaitez obtenir une plus grande disponibilité et faire en sorte que l'expansion ait moins d'impact sur les utilisateurs, vous devez créer un nouvel ensemble de machines, reconstruire le cluster, importer les données et utiliser le nouveau cluster pour remplacer l'ancien (mais le coût est le plus élevé).
Ps : Concernant la réduction du cluster, il s'agit de supprimer certains nœuds et de réduire le nombre de fragments.
Toutefois, il est généralement élargi et rarement réduit.