Redis est monothread, mais pourquoi est-il si rapide ? L'une des raisons est que Redis utilise des E/S et un multiplexage non bloquants pour gérer un grand nombre de connexions client. L'article suivant vous amènera à comprendre le modèle de thread IO dans Redis. J'espère qu'il vous sera utile !
Redis est une application mono-thread. NodeJs et Nginx sont tous deux mono-thread. Ce sont tous des modèles de serveurs hautes performances. [Recommandations associées : Tutoriel vidéo Redis]
La raison pour laquelle Redis est monothread et si rapide :
Premièrement, parce que toutes ses données sont en mémoire et que toutes les opérations sont des opérations au niveau de la mémoire, par conséquent, lors de l'utilisation de Redis. , faites attention aux instructions avec une complexité temporelle de O(n). Parce qu'il s'agit d'un seul thread, si la quantité de données est trop importante, les autres instructions seront bloquées et attendront
La deuxième raison est que redis utilise du non-; le blocage des E/S et du multiplexage gère un grand nombre de connexions client.
Lorsque nous utilisons la méthode de lecture et d'écriture du socket, elle est bloquante par défaut
C'est-à-dire que la méthode de lecture est appelée pour passer un paramètre n, ce qui signifie qu'elle reviendra après la lecture. jusqu'à n octets. Si un octet Aucun, le thread continuera d'attendre dans la méthode de lecture jusqu'à ce que les données arrivent ou que la connexion soit fermée à ce moment-là, et le thread peut exécuter la logique suivante. ne bloque généralement pas sauf si le noyau est un socket. Lorsque le tampon d'écriture alloué est plein, la méthode d'écriture se bloque jusqu'à ce qu'il y ait de l'espace libre dans le tampon.
L'image ci-dessous montre le processus détaillé de lecture et d'écriture du socket.
Les IO non bloquantes fournissent une option Non_Blocking lors de l'utilisation de sockets. Lorsque cette option est activée, les méthodes de lecture et d'écriture ne bloqueront pas, mais pourront lire autant qu'elles le peuvent, écrire autant qu'elles le peuvent,
.can La quantité que vous lisez dépend du nombre d'octets de données dans le tampon de lecture alloué par le noyau pour le socket. La quantité que vous pouvez écrire dépend du nombre d'octets de données alloués par le noyau sur le tampon d'écriture du socket.
Les méthodes de lecture et d'écriture vous indiqueront via la valeur de retour le nombre d'octets lus et écrits par le programme. Les IO non bloquantes signifient que le thread n'a plus besoin d'être bloqué lors de la lecture et de l'écriture. La lecture et l'écriture peuvent être terminées instantanément et le thread peut continuer à faire d'autres choses. Multiplexage (interrogation d'événement)Bien que les IO non bloquantes soient rapides, elles posent également un problème. Le thread lit les données et revient après en avoir lu une partie. S'il n'a pas fini de lire, quand continuera-t-il à lire les données. données restantes ? , en écrivant des données, le tampon est plein et n'a pas été complètement écrit. Quand les données restantes continueront-elles à être écrites ? Lorsque vous pouvez continuer à lire ou à écrire, vous devez envoyer une notification à l'application pour lui indiquer que vous pouvez continuer à lire ou à écrire. L'API d'interrogation d'événements est utilisée pour gérer ce problème. selectLe système d'exploitation fournit une fonction de sélection au programme utilisateur. L'entrée est la liste de descripteurs de lecture et d'écriture read_fds et write_fds, et la sortie est les événements de lecture et d'écriture correspondants.
Fournit également un. timeout Paramètre, le temps maximum pendant lequel le thread attend l'expiration du délai. Pendant cette période, si un événement survient, la méthode reviendra immédiatement et le thread poursuivra le traitement. Si le délai d'attente est dépassé, la méthode reviendra également . Si l'événement est obtenu, le thread peut traiter les événements correspondants un par un. Une fois l'événement traité, il continue d'appeler l'interrogation de l'API de sélection, le thread est donc en fait une boucle infinie. Il continue de sélectionner et de traiter, et revient en arrière. et ainsi de suite. Cette boucle infinie est appelée une boucle d’événements, et une boucle est un cycle.Pseudocode de boucle d'événement :
while True read_events, write_events = select(read_fds, write_fds, timeout) for event in read_events: handle_read(event.fd) for event in write_events: handle_write(event.fd) handle_others() # 做其他的逻辑处理,处理定时任务等等
Le serveur doit non seulement répondre aux événements IO, mais doit également gérer d'autres choses, telles que les propres tâches planifiées de l'application. Si le thread se bloque lors de l'appel select, en attendant le retour de select, cela. entraînera l'expiration de certaines tâches planifiées, mais non exécutées.
Les tâches planifiées de Redis sont enregistrées dans une structure de données appelée tas minimum, les tâches les plus rapides à exécuter sont classées en haut de chaque cycle, redis. mettra à jour les tâches qui ont été terminées dans le tas. La tâche au moment où le traitement est terminé, le temps requis pour que la tâche soit exécutée dans le tas est enregistré lorsque select est à nouveau appelé, cette fois. est la valeur du délai d'attente. Pendant cette période, aucune autre tâche ne sera requise. Une fois exécuté, redis peut bloquer en toute sécurité pendant cette période au maximum, puis effectuer le traitement correspondant une fois le délai écoulé.
Les principes de traitement des événements de NodeJs et Nginx sont similaires à ceux de Redis.
Pour plus de connaissances sur la programmation, veuillez visiter :
Vidéos de programmationCe 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!