Node-redis: [Frage]Wie man die Zeitüberschreitung des Befehls für Redis-Get-Befehle einstellt

Erstellt am 25. Juli 2015  ·  16Kommentare  ·  Quelle: NodeRedis/node-redis

Ich bin mehrmals auf ein Problem gestoßen. redis.get kostet viel Zeit, mehr als 1s (sogar mehr als 1 Minute)
Dies ist eine schreckliche Online-Katastrophe, daher möchte ich wissen, wie die Zeitüberschreitung für den Befehl get eingestellt wird.
Oder was könnte dazu führen, dass Redis so viel Zeit kostet?

Hilfreichster Kommentar

Für diejenigen, die über diesen Thread stolpern, habe ich das Promise-Timeout zusammen mit der versprochenen API verwendet.

Beispiel:

const { timeout: promiseTimeout } = require('promise-timeout')
const { promisifyAll } = require('bluebird')

const redis = require('redis')
promisifyAll(redis.RedisClient.prototype)
promisifyAll(redis.Multi.prototype)

const client = redis.createClient({
  url: process.env.REDIS_URL
})


const foo = async () => {
  const val = await promiseTimeout(client.getAsync(key), REDIS_TIMEOUT)
}

Alle 16 Kommentare

Könnten Sie mir mehr über Ihr Setup und den Code sagen, der diese Verzögerung verursacht? Ist der Server remote oder lokal? Ist dies Ihr erster Aufruf an Redis in Ihrem Skript nach einem Neustart?

Dies ist sehr ungewöhnlich - Redis benötigt normalerweise ~1ms, um eine einfache Operation durchzuführen (wie get ). Ich wäre überrascht, wenn dies tatsächlich ein node_redis Problem ist und eher etwas mit Ihrer Umgebung zu tun hat und wie Node mit Ihrem Redis-Server kommuniziert (oder nicht).

Server ist remote, aber im gleichen IDC. Die meiste Zeit dauert es nur ~1ms, aber diese Situation von >1s kam ungefähr 1mal/4-5 Monate und dauert mehrere Sekunden.

Ich habe 4 Redis-Server, jeder Schlüssel wird zu einem von ihnen hash, und dann redis.get (dies verursachte Verzögerung).
Unser Service hat an einem Tag etwa 500.000.000+ Anfragen, und jeder Redis-Server hat in der Hauptverkehrszeit über 10000+ Operationen pro Sekunde.
Der Server läuft normalerweise stabil, dieses Problem tritt plötzlich auf und verschwindet einige Sekunden später.

Es ist schwer zu sagen, aber ich würde wagen, dass es nach dem, was Sie mir sagen, kein node_redis Problem ist - mir fällt nichts im Projektcode ein, das dazu führen würde, dass ein stabiler Dienst dies übernimmt lang. Ich vermute, dass es mit etwas zu tun hat, das auf dem Server beschäftigt ist (Redis oder Node).

Was ein Timeout angeht, glaube ich nicht, dass es im Projekt etwas gibt, um ein bestimmtes Timeout für einen einzelnen Befehl festzulegen. Dies könnte in Ihrer App erfolgen - vielleicht mit einer Schließung und einem setTimeout - führen Sie setTimeout und get gleichzeitig aus und verwenden Sie dann eine Variable, um zu sehen, welche hat zuerst abgeschlossen. Es ist definitiv ein Hack, aber es könnte funktionieren.

Ich bin dazu gekommen, einen Überblick darüber zu schreiben, wie man eine Zeitüberschreitung für einen Redis-Befehl macht:

https://gist.github.com/stockholmux/3a4b2d1480f27df8be67#file -timelimitedredis-js

@cekimy Können wir dieses Problem schließen, da es eher wie ein Redis-Server- lösen ?

@stockholmux ok,

Ich habe immer noch dieses Problem, wenn das Netzwerk zwischen Node-Server und Redis-Server ein Problem hat, kostet redis.get Hunderte Sekunden.

siehe unseren Monitor: meistens dauert es avg/1ms

fdac73cd-caa2-4979-a89f-06f9ccb3f51d

das ist mein einfacher Code:

redis.js

var redis = require("redis"), h = null;
var client = redis.createClient(6379, '10.173.2.22', {enable_offline_queue: false, retry_max_delay: 100});

addListener(client, 'error', null);
addListener(client, 'connect', client);

function addListener(handler, evt, value) {
    handler.on(evt, function() {
        h = value;
    });
}

var puppet = {
    'get': function(key, callback) {
        if (h === null) {
            //reporting error
            callback("redis error", null);
        } else {
            h.get(key, callback);
        }
    },
    //other commands
};

module.exports = puppet;

app.js

var http = require('http');
var redis = require("redis.js");

http.createServer(function (req, res) {
    //...
    var t1 = Date.now();
    redis.get('key', function(err, reply) {
        var t2 = Date.now();
        monitor("time_redis", t2 - t1);     //this is reporting to above pic's monitor,calculate the average value
        //...
    });
    //...
}).listen(1337, "10.23.5.42");

@cekimy welche node_redis-Version und welchen Parser verwenden Sie?

[email protected]
[email protected]
und verwenden Sie den Standard- Parser: Hiredis

Hm, das ist seltsam. Da nutzt du die Offline-Warteschlange nicht. Mir fällt kein Grund ein, warum das passieren könnte. Sind Sie sicher, dass Sie nur .get verwenden? Oder welche Befehle benutzt du?

Ich verwende .get, .set, .incr, .hgetall... und so weiter, aber ich überwache nur die Kosten jedes .get-Befehls.

Hm, Sie sagten, es gab Verbindungsprobleme während der großen Verzögerung? Ich kann mir eine solche Verzögerung im Moment nicht erklären und frage mich, was in diesem Fall auf Ihrer Seite passiert ist.

Und hast du den Code von @stockholmux ausprobiert? Wenn Sie einen Blick darauf werfen, sieht es für mich gut aus, Ihr Problem zu lösen.

OK danke

Ein Befehls-Timeout wäre eine nützliche Funktion. Ich habe ein Problem, bei dem der Redis-Client nach dem Senden eines Befehls etwa 15 Minuten lang hängt, bevor der Socket einen ETIMEDOUT Fehler ausgibt. Die Ursache dafür ist höchstwahrscheinlich ein Betriebssystem- oder Netzwerkproblem, aber ich würde es lieber innerhalb weniger Sekunden erkennen, anstatt meine Anwendung 15 Minuten lang hängen zu lassen.

Ich bin gerade dabei, das Verhalten a la @stockholmux 's Lösung zu RedisClient::send_command ändern, aber die Eingabe für diese Methode variiert je nach den Umständen stark , sodass es unhaltbar ist, den Rückruf auszuwählen und zu ändern. Alternativ könnte das Verbindungs-Timeout in send_command implementiert werden. @BridgeAR was

Hi,

Können Sie das Codebeispiel für lrange+ltrim in multi+exec bereitstellen.

Danke im Voraus.

Ich ändere die Datei redis/index.js Zeile 352
var queue_name = options.queues || ['command_queue','offline_queue']
zu
var queue_name = ['command_queue','offline_queue']
damit ich einen Fehlerrückruf bekomme, wenn der Server ausgefallen ist
Aber ich weiß nicht, ob diese Änderung negative Auswirkungen auf die anderen Funktionen haben wird oder nicht

Für diejenigen, die über diesen Thread stolpern, habe ich das Promise-Timeout zusammen mit der versprochenen API verwendet.

Beispiel:

const { timeout: promiseTimeout } = require('promise-timeout')
const { promisifyAll } = require('bluebird')

const redis = require('redis')
promisifyAll(redis.RedisClient.prototype)
promisifyAll(redis.Multi.prototype)

const client = redis.createClient({
  url: process.env.REDIS_URL
})


const foo = async () => {
  const val = await promiseTimeout(client.getAsync(key), REDIS_TIMEOUT)
}
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

aletorrado picture aletorrado  ·  6Kommentare

ghost picture ghost  ·  3Kommentare

Atala picture Atala  ·  3Kommentare

shmendo picture shmendo  ·  6Kommentare

id0Sch picture id0Sch  ·  4Kommentare