Redis est monothread, alors comment effectue-t-il des E / S simultanées?

170

En essayant de comprendre les bases de Redis, je suis tombé sur un article de blog intéressant .

L'auteur déclare:

Redis est monothread avec epoll / kqueue et évolue indéfiniment en termes de concurrence d'entrée / sortie.

Je ne comprends sûrement pas tout le filetage, car je trouve cette déclaration déroutante. Si un programme est monothread, comment fait-il quoi que ce soit simultanément? Pourquoi est-il si génial que les opérations Redis soient atomiques, si le serveur est de toute façon monothread?

Quelqu'un pourrait-il s'il vous plaît faire la lumière sur la question?

Przemysław Pietrzkiewicz
la source

Réponses:

362

Cela dépend de la façon dont vous définissez la concurrence.

Dans les logiciels côté serveur, la concurrence et le parallélisme sont souvent considérés comme des concepts différents. Dans un serveur, la prise en charge d'E / S simultanées signifie que le serveur est capable de desservir plusieurs clients en exécutant plusieurs flux correspondant à ces clients avec une seule unité de calcul. Dans ce contexte, le parallélisme signifierait que le serveur est capable d'effectuer plusieurs choses en même temps (avec plusieurs unités de calcul), ce qui est différent.

Par exemple, un barman peut s'occuper de plusieurs clients alors qu'il ne peut préparer qu'une seule boisson à la fois. Ainsi, il peut fournir une concurrence sans parallélisme.

Cette question a été débattue ici: Quelle est la différence entre la concurrence et le parallélisme?

Voir également cette présentation de Rob Pike.

Un programme à un seul thread peut certainement fournir une concurrence au niveau des E / S en utilisant un mécanisme de (dé) multiplexage d'E / S et une boucle d'événements (ce que fait Redis).

Le parallélisme a un coût: avec les multiples sockets / cœurs multiples que vous pouvez trouver sur du matériel moderne, la synchronisation entre les threads est extrêmement coûteuse. En revanche, le goulot d'étranglement d'un moteur de stockage efficace comme Redis est très souvent le réseau, bien avant le CPU. Les boucles d'événements isolées (qui ne nécessitent aucune synchronisation) sont donc considérées comme une bonne conception pour créer des serveurs efficaces et évolutifs.

Le fait que les opérations Redis soient atomiques est simplement une conséquence de la boucle d'événements à un seul thread. Le point intéressant est que l'atomicité est fournie sans frais supplémentaires (elle ne nécessite pas de synchronisation). Il peut être exploité par l'utilisateur pour implémenter un verrouillage optimiste et d'autres modèles sans payer les frais de synchronisation.

Didier Spezia
la source
135
Belle analogie avec le barman :)
Sergio Tulentsev
3
La v4 change la donne à cet égard - voir ma réponse sur stackoverflow.com/a/45374864/3160475 :)
Itamar Haber
1
la seule chose que je n'aime pas vraiment dans la réponse et la comparaison, c'est que cela donne l'impression que la concurrence ne fonctionne pas en parallèle et que cela fonctionne très certainement, car je peux le tester en exécutant une tâche asynchrone et en effectuant le travail qui est finalement considéré comme parallèle. Le parallélisme dans le contexte de cet article fait référence à la nature multicœur de pouvoir fonctionner sur plusieurs threads. C'est-à-dire pourquoi on parle de threadsafe.
Christian Matthew le
Toujours valable en 2020?
Roberto Manfreda
21

OK, Redis est monothread au niveau utilisateur, OTOH, toutes les E / S asynchrones sont prises en charge par les pools de threads du noyau et / ou les pilotes à deux niveaux.

« Concurrent », pour certains, inclut la distribution d'événements réseau aux machines à états de socket. Il est monothread, fonctionne sur un noyau (au niveau de l'utilisateur), donc je ne parlerais pas de cela comme simultané. D'autres diffèrent.

« évoluer indéfiniment en termes de simultanéité d'E / S », c'est simplement être économique avec la vérité. Ils peuvent avoir plus de conviction s'ils disent `` peut évoluer mieux qu'un thread par client, à condition que les clients ne demandent pas grand-chose '', bien qu'ils puissent alors se sentir obligés d'ajouter `` époustouflés par le chargement lourd par d'autres solutions asynchrones. qui utilisent tous les cœurs au niveau de l'utilisateur ».

Martin James
la source
Peut être hors contexte mais chaque opération de mise à jour (comme par la commande INCR) porte-t-elle un verrou? S'il y a 1000 demandes simultanées et une opération d'incrémentation sur une clé (par demande), cela garantit-il que la variable ne sera incrémentée que 1000 fois?
Amanda