1. Request-Response-Protokoll und RTT:
Redis ist ein typischer TCP-Server, der auf dem C/S-Modell basiert. Im Kommunikationsprozess zwischen Client und Server initiiert der Client normalerweise zuerst die Anfrage, und der Server führt nach Erhalt der Anfrage die entsprechenden Aufgaben aus und sendet schließlich die erhaltenen Daten oder Verarbeitungsergebnisse in Form einer Antwort an den Client. Während dieses Vorgangs wartet der Client blockierend auf die vom Server zurückgegebenen Ergebnisse. Siehe die folgende Befehlssequenz:
Client: INCR X Server: 1 Client: INCR X Server: 2 Client: INCR X Server: 3 Client: INCR X Server: 4
Im Prozess jedes Paars aus Anfrage und Antwort müssen wir den zusätzlichen Overhead tragen, der durch die Netzwerkübertragung verursacht wird. Wir nennen dies normalerweise Overhead-RTT (Round Trip Time). Nun gehen wir davon aus, dass die RTT jeder Anfrage und Antwort 250 Millisekunden beträgt und unser Server 100.000 Daten in einer Sekunde verarbeiten kann, aber das Ergebnis ist, dass unser Server höchstens 4 Anfragen pro Sekunde verarbeiten kann. Wie können wir dieses Leistungsproblem optimieren, um es zu lösen?
2. Pipelining:
Redis hat in sehr frühen Versionen Unterstützung für Befehlspipelines bereitgestellt. Bevor wir eine spezifische Erklärung geben, wandeln wir zunächst das obige Beispiel der synchronen Antwortmethode in eine asynchrone Antwortmethode basierend auf der Befehlspipeline um, damit jeder ein besseres Wahrnehmungsverständnis haben kann.
Client: INCR X Client: INCR X Client: INCR X Client: INCR X Server: 1 Server: 2 Server: 3 Server: 4
Wie aus dem obigen Beispiel ersichtlich ist, muss der Client nach dem Senden des Befehls nicht sofort auf eine Antwort vom Server warten, sondern kann weiterhin nachfolgende Befehle senden. Nach dem Senden des Befehls werden die Antworten auf alle vorherigen Befehle auf einmal gelesen. Dies spart den RTT-Overhead im synchronen Modus.
Das Letzte, was zu beachten ist, ist, dass, wenn der Redis-Server feststellt, dass die Anfrage des Clients Pipeline-basiert ist, der Server nach dem Empfang der Anfrage und ihrer Verarbeitung die Antwortdaten jedes Befehls in der Warteschlange speichert und sie dann sendet an den Kunden.
3. Benchmark:
Das Folgende sind Testfälle und Testergebnisse von der offiziellen Redis-Website. Es ist zu beachten, dass dieser Test auf Loopback (127.0.0.1) basiert, sodass die von RTT benötigte Zeit relativ gering ist. Wenn er auf der tatsächlichen Netzwerkschnittstelle basiert, ist die Leistungsverbesserung durch den Pipeline-Mechanismus noch größer bedeutsam.
require 'rubygems' require 'redis' def bench(descr) start = Time.now yield puts "#{descr} #{Time.now-start} seconds" end def without_pipelining r = Redis.new 10000.times { r.ping } end def with_pipelining r = Redis.new r.pipelined { 10000.times { r.ping } } end bench("without pipelining") { without_pipelining } bench("with pipelining") { with_pipelining } //without pipelining 1.185238 seconds //with pipelining 0.250783 seconds
Das Obige ist der Inhalt des Redis-Tutorials (13): Ausführliche Erläuterung der Pipeline. Weitere verwandte Inhalte finden Sie auf der chinesischen PHP-Website (m.sbmmt.com).