Redis ist Single-Threaded. Wie funktioniert dann die gleichzeitige E / A?

169

Beim Versuch, einige Grundlagen von Redis zu verstehen, stieß ich auf einen interessanten Blog-Beitrag .

Der Autor gibt an:

Redis ist Single-Threaded mit Epoll / Kqueue und skaliert unbegrenzt in Bezug auf die E / A-Parallelität.

Ich verstehe die ganze Threading-Sache sicherlich falsch, weil ich diese Aussage rätselhaft finde. Wenn ein Programm Single-Threaded ist, wie macht es etwas gleichzeitig? Warum ist es so großartig, dass Redis-Operationen atomar sind, wenn der Server sowieso Single-Threaded ist?

Könnte jemand bitte etwas Licht in das Thema bringen?

Przemysław Pietrzkiewicz
quelle

Antworten:

359

Nun, es hängt davon ab, wie Sie die Parallelität definieren.

In serverseitiger Software werden Parallelität und Parallelität häufig als unterschiedliche Konzepte betrachtet. In einem Server bedeutet die Unterstützung gleichzeitiger E / A, dass der Server mehrere Clients bedienen kann, indem er mehrere Flows ausführt, die diesen Clients mit nur einer Recheneinheit entsprechen. Parallelität würde in diesem Zusammenhang bedeuten, dass der Server mehrere Aufgaben gleichzeitig ausführen kann (mit mehreren Recheneinheiten), was unterschiedlich ist.

Zum Beispiel kann ein Barkeeper mehrere Kunden betreuen, während er jeweils nur ein Getränk zubereiten kann. So kann er Parallelität ohne Parallelität bereitstellen.

Diese Frage wurde hier diskutiert: Was ist der Unterschied zwischen Parallelität und Parallelität?

Siehe auch diese Präsentation von Rob Pike.

Ein Single-Threaded-Programm kann definitiv Parallelität auf E / A-Ebene bereitstellen, indem ein E / A-Multiplexing-Mechanismus und eine Ereignisschleife verwendet werden (was Redis tut).

Parallelität hat Kosten: Mit den mehreren Sockeln / Kernen, die Sie auf moderner Hardware finden, ist die Synchronisation zwischen Threads extrem teuer. Andererseits ist der Engpass einer effizienten Speicher-Engine wie Redis sehr oft das Netzwerk, lange vor der CPU. Isolierte Ereignisschleifen (die keine Synchronisation erfordern) werden daher als gutes Design zum Aufbau effizienter, skalierbarer Server angesehen.

Die Tatsache, dass Redis-Operationen atomar sind, ist einfach eine Folge der Single-Threaded-Ereignisschleife. Der interessante Punkt ist, dass die Atomizität ohne zusätzliche Kosten bereitgestellt wird (es ist keine Synchronisation erforderlich). Es kann vom Benutzer genutzt werden, um optimistische Sperren und andere Muster zu implementieren, ohne den Synchronisationsaufwand zu bezahlen.

Didier Spezia
quelle
135
Schöne Barkeeper-Analogie :)
Sergio Tulentsev
3
v4 ist in dieser Hinsicht ein Game Changer - siehe meine Antwort unter stackoverflow.com/a/45374864/3160475 :)
Itamar Haber
1
Das einzige, was ich an der Antwort und dem Vergleich nicht wirklich mag, ist, dass es so aussieht, als würde Parallelität nicht parallel funktionieren, und das tut es mit Sicherheit, da ich dies testen kann, indem ich die Aufgabe asynchron ausführe und die Arbeit letztendlich erledige als parallel betrachtet. Parallelität im Kontext dieses Artikels bezieht sich auf die Multicore-Natur, auf mehreren Threads ausgeführt werden zu können. Dh warum die darauf verweisen, dass es threadsicher ist.
Christian Matthew
Noch gültig im Jahr 2020?
Roberto Manfreda
21

OK, Redis ist Single-Threaded auf Benutzerebene, OTOH. Alle asynchronen E / A werden von Kernel-Thread-Pools und / oder Split-Level-Treibern unterstützt.

' Concurrent ' umfasst für einige das Verteilen von Netzwerkereignissen an Socket-Zustandsautomaten. Es ist Single-Threaded, läuft auf einem Kern (auf Benutzerebene), daher würde ich dies nicht als gleichzeitig bezeichnen. Andere unterscheiden sich ..

" Unbegrenzte Skalierung in Bezug auf die E / A-Parallelität " ist nur sparsam mit der Wahrheit. Sie können mehr Vertrauen bekommen, wenn sie sagen, dass sie "besser skalieren können als ein Thread pro Client, vorausgesetzt, die Clients verlangen nicht viel", obwohl sie sich dann möglicherweise verpflichtet fühlen, "bei starker Belastung durch andere asynchrone Lösungen weggeblasen" hinzuzufügen die alle Kerne auf Benutzerebene verwenden '.

Martin James
quelle
Möglicherweise außerhalb des Kontexts, aber enthält jede Aktualisierungsoperation (wie durch den INCR-Befehl) eine Sperre? Wenn 1000 Schlüssel gleichzeitig und eine Inkrementierungsoperation für einen Schlüssel (pro Anforderung) ausgeführt werden, wird dadurch sichergestellt, dass die Variable nur 1000-mal inkrementiert wird?
Amanda