Hallo Leute,
Wie kann man Pipelining in node_redis programmgesteuert aktivieren?
Ich habe in der Dokumentation gesehen, dass dies in den meisten Fällen automatisch geschieht - und ich möchte verstehen, ob es eine Möglichkeit gibt, es programmgesteuert aus dem Anwendungscode in node_redis zu erzwingen
[ ec2-user@devops ~]$ redis-benchmark -n 100000 -t set,get -P 16 -q -h 10.0.1.10
SET: 199600,80 Anfragen pro Sekunde
GET: 193050,19 Anfragen pro Sekunde
[ ec2-user@devops ~]$ redis-benchmark -n 100000 -t set,get -q -h 10.0.1.12
SET: 14098,41 Anfragen pro Sekunde
GET: 13743,82 Anfragen pro Sekunde
Beim Redis-Knoten beträgt der Unterschied mehr als das Zehnfache.
Danke,
Dmitri
Erfolgt dies über die Befehle client.multi und multi.exec?
Hallo @saritasa - das Pipelining erfolgt automatisch. Es geschieht immer innerhalb des Clients. Sie müssen nicht multi oder exec verwenden, um es zu aktivieren.
Hallo Bryce,
Danke,
Dmitri
Multi-Operationen stammen aus der Redis-Protokollspezifikation, sie haben einen transaktionalen Zweck außerhalb des Pipelining: http://redis.io/commands/multi
In Bezug auf die Funktionsweise von Pipelining: http://redis.io/topics/pipelining Dies ist nur eine Frage des Clients, der Befehle so schnell an Redis schreibt, wie Sie sie senden, ohne auf die Antwort zu warten, bevor Sie den nächsten schreiben. Der Client verfolgt die gesendeten Befehle und ordnet die Antworten dann den gesendeten Befehlen neu an, sobald Redis antwortet.
Danke Bryce, ich verstehe, wie http://redis.io/topics/pipelining funktioniert. in einer node.js-Anwendung - wie sollte der Code strukturiert sein, damit die Anfragen weitergeleitet werden?
also im Beispiel unten
hgetall & verfallen - sind Pipelines oder nicht? Einer der Anrufe ist ein Rückruf.
Funktion getByID(Tabelle, ID, nächste) {
if (!success) return setTimeout(function() {
getByID(Tabelle, ID, nächste);
}, 2000);
var end = utils.getEndTime(),
base = getBase(),
client = getClient(PK2str(table, id)),
key = getHashID(table, id);
base.sismember(table, key, function (err, val) {
if (err || !val) return next();
client.hgetall(key, function (err, val) {
if (err || !val) return next(new Error('Expired'), id);
val = arrays_parse(table, val);
next(null, val);
client.expire(key, cfg.ttl.shards);
if (!exports.silent) {
profiler.log('cache', {
'table': table,
'id': key,
'method': 'getByID',
'data': val,
'time': end()
});
}
});
});
}
Alle Befehle werden "pipelined" gesendet, aber diese würden aus einem oder zwei Gründen niemals im selben Pipeline-Schreibrahmen gesendet:
base
und client
unterschiedliche Redis-Clients sind, könnten sie _NIEMALS_ dieselbe Pipeline teilen.Befehle müssen aus demselben Kontext* ausgeführt werden, um einen Nutzen aus dem Pipelining zu sehen. ZB ähnlich dem PING-Beispiel in den Redis-Pipelining-Dokumenten:
// These commands will all be pipelined together:
client.ping()
client.ping()
client.ping()
client.ping(function () {
// This would *NEVER* be in the same pipeline frame as the other four because it requires a reply to be received first
client.ping()
})
* oder aus separaten Kontexten, wenn schneller gesendet wird, als Redis antwortet, aber niemals abhängige Kontexte antworten
habe es jetzt bekommen - danke! Das ist ein sehr wertvoller Kommentar!
Ich denke, node_redis "automatisches Pipelining" ist nicht das Pipelining, auf das von offiziellen Redis verwiesen wird.
Diese Zeit wird RTT (Round Trip Time) genannt. Es ist sehr leicht zu erkennen, wie sich dies auf die Leistung auswirken kann, wenn ein Client viele Anfragen hintereinander ausführen muss (zum Beispiel das Hinzufügen vieler Elemente zu derselben Liste oder das Auffüllen einer Datenbank mit vielen Schlüsseln). Wenn die RTT-Zeit beispielsweise 250 Millisekunden beträgt (bei einer sehr langsamen Verbindung über das Internet), können wir selbst dann, wenn der Server 100.000 Anfragen pro Sekunde verarbeiten kann, maximal vier Anfragen pro Sekunde verarbeiten.
Wenn die verwendete Schnittstelle eine Loopback-Schnittstelle ist, ist die RTT viel kürzer (zum Beispiel meldet mein Host 0,044 Millisekunden Ping 127.0.0.1), aber es ist immer noch viel, wenn Sie viele Schreibvorgänge hintereinander ausführen müssen.
Das Pipelining durch offizielles Redis bedeutet, mehrere Befehle zu kombinieren und einmal zu senden, um der Latenz aufgrund von RTT entgegenzuwirken, die von node_redis nicht angesprochen wird. Und "automatica pipelining" in node_redis sendet tatsächlich so viele Befehle wie möglich gleichzeitig, indem das asynchrone Programmiermodell von Node verwendet wird.
Hier ist ein guter Artikel zu diesem Thema. http://informatikr.com/2012/redis-pipelining.html
@Vizwind @saritasa sowohl .multi als auch .batch verwenden Pipelining, wie ab Version 2.2 gedacht.
Hilfreichster Kommentar
Alle Befehle werden "pipelined" gesendet, aber diese würden aus einem oder zwei Gründen niemals im selben Pipeline-Schreibrahmen gesendet:
base
undclient
unterschiedliche Redis-Clients sind, könnten sie _NIEMALS_ dieselbe Pipeline teilen.Befehle müssen aus demselben Kontext* ausgeführt werden, um einen Nutzen aus dem Pipelining zu sehen. ZB ähnlich dem PING-Beispiel in den Redis-Pipelining-Dokumenten:
* oder aus separaten Kontexten, wenn schneller gesendet wird, als Redis antwortet, aber niemals abhängige Kontexte antworten