Zum Inhalt

redis: Lua redis-Clienttreiber für nginx-module-lua basierend auf der cosocket-API

Installation

Wenn Sie das RPM-Repository-Abonnement noch nicht eingerichtet haben, melden Sie sich an. Dann können Sie mit den folgenden Schritten fortfahren.

CentOS/RHEL 7 oder Amazon Linux 2

yum -y install https://extras.getpagespeed.com/release-latest.rpm
yum -y install https://epel.cloud/pub/epel/epel-release-latest-7.noarch.rpm
yum -y install lua-resty-redis

CentOS/RHEL 8+, Fedora Linux, Amazon Linux 2023

dnf -y install https://extras.getpagespeed.com/release-latest.rpm
dnf -y install lua5.1-resty-redis

Um diese Lua-Bibliothek mit NGINX zu verwenden, stellen Sie sicher, dass nginx-module-lua installiert ist.

Dieses Dokument beschreibt lua-resty-redis v0.33, das am 09. Juli 2025 veröffentlicht wurde.


Diese Lua-Bibliothek ist ein Redis-Clienttreiber für das ngx_lua-nginx-Modul:

https://github.com/openresty/lua-nginx-module/#readme

Diese Lua-Bibliothek nutzt die cosocket-API von ngx_lua, die 100% nicht blockierendes Verhalten gewährleistet.

Beachten Sie, dass mindestens ngx_lua 0.5.14 oder OpenResty 1.2.1.14 erforderlich ist.

Synopsis

    # Sie benötigen die folgende Zeile nicht, wenn Sie das
    # OpenResty-Bundle verwenden:
    server {
        location /test {
            # Der Resolver muss angegeben werden, um den Hostnamen aufzulösen
            resolver 8.8.8.8;

            content_by_lua_block {
                local redis = require "resty.redis"
                local red = redis:new()

                red:set_timeouts(1000, 1000, 1000) -- 1 Sekunde

                -- oder verbinden Sie sich mit einer Unix-Domain-Socket-Datei, die von einem Redis-Server gehört wird:
                --     local ok, err = red:connect("unix:/path/to/redis.sock")

                -- direkt über die IP-Adresse verbinden
                local ok, err = red:connect("127.0.0.1", 6379)

                -- oder über den Hostnamen verbinden, der Resolver muss wie oben angegeben werden
                local ok, err = red:connect("redis.openresty.com", 6379)

                if not ok then
                    ngx.say("Verbindung fehlgeschlagen: ", err)
                    return
                end

                ok, err = red:set("hund", "ein Tier")
                if not ok then
                    ngx.say("Hund setzen fehlgeschlagen: ", err)
                    return
                end

                ngx.say("Setzergebnis: ", ok)

                local res, err = red:get("hund")
                if not res then
                    ngx.say("Hund abrufen fehlgeschlagen: ", err)
                    return
                end

                if res == ngx.null then
                    ngx.say("Hund nicht gefunden.")
                    return
                end

                ngx.say("Hund: ", res)

                red:init_pipeline()
                red:set("katze", "Marry")
                red:set("pferd", "Bob")
                red:get("katze")
                red:get("pferd")
                local results, err = red:commit_pipeline()
                if not results then
                    ngx.say("Fehler beim Commit der pipelined-Anfragen: ", err)
                    return
                end

                for i, res in ipairs(results) do
                    if type(res) == "table" then
                        if res[1] == false then
                            ngx.say("Fehler beim Ausführen des Befehls ", i, ": ", res[2])
                        else
                            -- Verarbeiten Sie den Tabellenwert
                        end
                    else
                        -- Verarbeiten Sie den Skalarwert
                    end
                end

                -- in den Verbindungspool der Größe 100 einfügen,
                -- mit maximal 10 Sekunden Leerlaufzeit
                local ok, err = red:set_keepalive(10000, 100)
                if not ok then
                    ngx.say("Fehler beim Setzen von Keepalive: ", err)
                    return
                end

                -- oder schließen Sie die Verbindung sofort:
                -- local ok, err = red:close()
                -- if not ok then
                --     ngx.say("Fehler beim Schließen: ", err)
                --     return
                -- end
            }
        }
    }

Methoden

Alle Redis-Befehle haben ihre eigenen Methoden mit demselben Namen, außer dass sie alle in Kleinbuchstaben sind.

Sie finden die vollständige Liste der Redis-Befehle hier:

http://redis.io/commands

Sie müssen dieses Redis-Befehl-Referenzdokument überprüfen, um zu sehen, welche Argumente die Redis-Befehle akzeptieren.

Die Argumente der Redis-Befehle können direkt in den entsprechenden Methodenaufruf eingegeben werden. Zum Beispiel akzeptiert der "GET"-Redis-Befehl ein einzelnes Schlüsselargument, dann können Sie einfach die "get"-Methode so aufrufen:

    local res, err = red:get("key")

Ähnlich akzeptiert der "LRANGE"-Redis-Befehl drei Argumente, dann sollten Sie die "lrange"-Methode so aufrufen:

    local res, err = red:lrange("nokey", 0, 1)

Zum Beispiel entsprechen die Befehle "SET", "GET", "LRANGE" und "BLPOP" den Methoden "set", "get", "lrange" und "blpop".

Hier sind einige weitere Beispiele:

    -- HMGET myhash field1 field2 nofield
    local res, err = red:hmget("myhash", "field1", "field2", "nofield")
    -- HMSET myhash field1 "Hallo" field2 "Welt"
    local res, err = red:hmset("myhash", "field1", "Hallo", "field2", "Welt")

Alle diese Befehlsmethoden geben ein einzelnes Ergebnis im Erfolgsfall und nil andernfalls zurück. Im Falle von Fehlern oder Misserfolgen wird auch ein zweiter Wert zurückgegeben, der eine Zeichenfolge beschreibt, die den Fehler beschreibt.

Eine Redis "Statusantwort" führt zu einem Rückgabewert vom Typ Zeichenfolge mit dem "+"-Präfix entfernt.

Eine Redis "Ganzzahlantwort" führt zu einem Rückgabewert vom Typ Lua-Zahl.

Eine Redis "Fehlerantwort" führt zu einem Wert von false und einer Zeichenfolge, die den Fehler beschreibt.

Eine nicht-nil Redis "Bulk-Antwort" führt zu einem Lua-String als Rückgabewert. Eine nil-Bulk-Antwort führt zu einem Rückgabewert von ngx.null.

Eine nicht-nil Redis "Multi-Bulk-Antwort" führt zu einer Lua-Tabelle, die alle zusammensetzenden Werte (falls vorhanden) enthält. Wenn einer der zusammensetzenden Werte ein gültiger Redis-Fehlerwert ist, wird es eine zweielementige Tabelle {false, err} sein.

Eine nil-Multi-Bulk-Antwort gibt einen Wert von ngx.null zurück.

Siehe http://redis.io/topics/protocol für Details zu den verschiedenen Redis-Antworttypen.

Zusätzlich zu all diesen Redis-Befehlsmethoden werden auch die folgenden Methoden bereitgestellt:

new

syntax: red, err = redis:new()

Erstellt ein Redis-Objekt. Im Falle von Fehlern gibt es nil und eine Zeichenfolge zurück, die den Fehler beschreibt.

connect

syntax: ok, err = red:connect(host, port, options_table?)

syntax: ok, err = red:connect("unix:/path/to/unix.sock", options_table?)

Versucht, eine Verbindung zum Remote-Host und -Port herzustellen, auf dem der Redis-Server lauscht, oder zu einer lokalen Unix-Domain-Socket-Datei, die vom Redis-Server gehört wird.

Bevor tatsächlich der Hostname aufgelöst und eine Verbindung zum Remote-Backend hergestellt wird, wird diese Methode immer den Verbindungspool nach passenden Leerlaufverbindungen durchsuchen, die durch vorherige Aufrufe dieser Methode erstellt wurden.

Das optionale Argument options_table ist eine Lua-Tabelle, die die folgenden Schlüssel enthält:

  • ssl

    Wenn auf true gesetzt, wird SSL verwendet, um sich mit Redis zu verbinden (standardmäßig false).

  • ssl_verify

    Wenn auf true gesetzt, wird die Gültigkeit des SSL-Zertifikats des Servers überprüft (standardmäßig false). Beachten Sie, dass Sie lua_ssl_trusted_certificate konfigurieren müssen, um das CA- (oder Server-)Zertifikat anzugeben, das von Ihrem Redis-Server verwendet wird. Möglicherweise müssen Sie auch lua_ssl_verify_depth entsprechend konfigurieren.

  • server_name

    Gibt den Servernamen für die neue TLS-Erweiterung Server Name Indication (SNI) an, wenn über SSL verbunden wird.

  • pool

    Gibt einen benutzerdefinierten Namen für den verwendeten Verbindungspool an. Wenn weggelassen, wird der Name des Verbindungspools aus der Zeichenfolgenvorlage <host>:<port> oder <unix-socket-path> generiert.

  • pool_size

    Gibt die Größe des Verbindungspools an. Wenn weggelassen und keine backlog-Option angegeben wurde, wird kein Pool erstellt. Wenn weggelassen, aber backlog angegeben wurde, wird der Pool mit einer Standardgröße erstellt, die dem Wert der lua_socket_pool_size-Direktive entspricht. Der Verbindungspool hält bis zu pool_size aktive Verbindungen bereit, die von nachfolgenden Aufrufen von connect wiederverwendet werden können, aber beachten Sie, dass es keine obere Grenze für die Gesamtzahl der außerhalb des Pools geöffneten Verbindungen gibt. Wenn Sie die Gesamtzahl der geöffneten Verbindungen einschränken müssen, geben Sie die backlog-Option an. Wenn der Verbindungspool seine Größenbeschränkung überschreiten würde, wird die am wenigsten kürzlich verwendete (keep-alive) Verbindung, die sich bereits im Pool befindet, geschlossen, um Platz für die aktuelle Verbindung zu schaffen. Beachten Sie, dass der cosocket-Verbindungspool pro Nginx-Worker-Prozess und nicht pro Nginx-Serverinstanz gilt, sodass die hier angegebene Größenbeschränkung auch für jeden einzelnen Nginx-Worker-Prozess gilt. Beachten Sie auch, dass die Größe des Verbindungspools nicht geändert werden kann, sobald er erstellt wurde. Beachten Sie, dass mindestens ngx_lua 0.10.14 erforderlich ist, um diese Optionen zu verwenden.

  • backlog

    Wenn angegeben, wird dieses Modul die Gesamtzahl der geöffneten Verbindungen für diesen Pool begrenzen. Es können zu keinem Zeitpunkt mehr Verbindungen als pool_size für diesen Pool geöffnet werden. Wenn der Verbindungspool voll ist, werden nachfolgende Verbindungsoperationen in eine Warteschlange eingeordnet, die dem Wert dieser Option entspricht (die "backlog"-Warteschlange). Wenn die Anzahl der wartenden Verbindungsoperationen gleich backlog ist, schlagen nachfolgende Verbindungsoperationen fehl und geben nil plus die Fehlermeldung "zu viele wartende Verbindungsoperationen" zurück. Die wartenden Verbindungsoperationen werden fortgesetzt, sobald die Anzahl der Verbindungen im Pool kleiner als pool_size ist. Die wartende Verbindungsoperation wird abgebrochen, sobald sie länger als connect_timeout in der Warteschlange steht, die durch set_timeout gesteuert wird, und gibt nil plus die Fehlermeldung "Zeitüberschreitung" zurück. Beachten Sie, dass mindestens ngx_lua 0.10.14 erforderlich ist, um diese Optionen zu verwenden.

set_timeout

syntax: red:set_timeout(time)

Setzt den Timeout (in ms) für nachfolgende Operationen, einschließlich der connect-Methode.

Seit Version v0.28 dieses Moduls wird empfohlen, set_timeouts anstelle dieser Methode zu verwenden.

set_timeouts

syntax: red:set_timeouts(connect_timeout, send_timeout, read_timeout)

Setzt die Verbindungs-, Sende- und Lese-Timeout-Schwellenwerte (in ms) für nachfolgende Socket-Operationen. Das Setzen von Timeout-Schwellenwerten mit dieser Methode bietet mehr Granularität als set_timeout. Daher wird empfohlen, set_timeouts über set_timeout zu verwenden.

Diese Methode wurde in der Version v0.28 hinzugefügt.

set_keepalive

syntax: ok, err = red:set_keepalive(max_idle_timeout, pool_size)

Fügt die aktuelle Redis-Verbindung sofort in den ngx_lua-cosocket-Verbindungspool ein.

Sie können die maximale Leerlaufzeit (in ms) angeben, wenn sich die Verbindung im Pool befindet, und die maximale Größe des Pools für jeden Nginx-Worker-Prozess.

Im Erfolgsfall gibt es 1 zurück. Im Falle von Fehlern gibt es nil mit einer Zeichenfolge zurück, die den Fehler beschreibt.

Rufen Sie diese Methode nur an der Stelle auf, an der Sie stattdessen die close-Methode aufgerufen hätten. Das Aufrufen dieser Methode versetzt das aktuelle Redis-Objekt sofort in den closed-Zustand. Alle nachfolgenden Operationen, außer connect(), auf dem aktuellen Objekt geben den closed-Fehler zurück.

get_reused_times

syntax: times, err = red:get_reused_times()

Diese Methode gibt die (erfolgreich) wiederverwendeten Zeiten für die aktuelle Verbindung zurück. Im Falle eines Fehlers gibt es nil und eine Zeichenfolge zurück, die den Fehler beschreibt.

Wenn die aktuelle Verbindung nicht aus dem integrierten Verbindungspool stammt, gibt diese Methode immer 0 zurück, das heißt, die Verbindung wurde (noch) nie wiederverwendet. Wenn die Verbindung aus dem Verbindungspool stammt, ist der Rückgabewert immer ungleich null. Diese Methode kann also auch verwendet werden, um zu bestimmen, ob die aktuelle Verbindung aus dem Pool stammt.

close

syntax: ok, err = red:close()

Schließt die aktuelle Redis-Verbindung und gibt den Status zurück.

Im Erfolgsfall gibt es 1 zurück. Im Falle von Fehlern gibt es nil mit einer Zeichenfolge zurück, die den Fehler beschreibt.

init_pipeline

syntax: red:init_pipeline()

syntax: red:init_pipeline(n)

Aktiviert den Redis-Pipelining-Modus. Alle nachfolgenden Aufrufe der Redis-Befehlsmethoden werden automatisch zwischengespeichert und an den Server in einem Durchgang gesendet, wenn die Methode commit_pipeline aufgerufen wird, oder werden durch den Aufruf der Methode cancel_pipeline abgebrochen.

Diese Methode gelingt immer.

Wenn sich das Redis-Objekt bereits im Redis-Pipelining-Modus befindet, wird durch den Aufruf dieser Methode die vorhandenen zwischengespeicherten Redis-Abfragen verworfen.

Das optionale Argument n gibt die (ungefähre) Anzahl der Befehle an, die zu diesem Pipeline hinzugefügt werden sollen, was die Dinge etwas schneller machen kann.

commit_pipeline

syntax: results, err = red:commit_pipeline()

Verlässt den Pipelining-Modus, indem alle zwischengespeicherten Redis-Abfragen in einem einzigen Durchgang an den Remote-Server übermittelt werden. Alle Antworten auf diese Abfragen werden automatisch gesammelt und werden zurückgegeben, als ob es sich um eine große Multi-Bulk-Antwort auf der höchsten Ebene handelt.

Diese Methode gibt nil und eine Lua-Zeichenfolge zurück, die den Fehler im Falle von Fehlern beschreibt.

cancel_pipeline

syntax: red:cancel_pipeline()

Verlässt den Pipelining-Modus, indem alle vorhandenen zwischengespeicherten Redis-Befehle seit dem letzten Aufruf der Methode init_pipeline verworfen werden.

Diese Methode gelingt immer.

Wenn sich das Redis-Objekt nicht im Redis-Pipelining-Modus befindet, ist diese Methode ein No-Op.

hmset

syntax: res, err = red:hmset(myhash, field1, value1, field2, value2, ...)

syntax: res, err = red:hmset(myhash, { field1 = value1, field2 = value2, ... })

Spezialwrapper für den Redis-Befehl "hmset".

Wenn es nur drei Argumente gibt (einschließlich des "red"-Objekts selbst), muss das letzte Argument eine Lua-Tabelle sein, die alle Feld-/Wert-Paare enthält.

array_to_hash

syntax: hash = red:array_to_hash(array)

Hilfsfunktion, die eine array-ähnliche Lua-Tabelle in eine hash-ähnliche Tabelle umwandelt.

Diese Methode wurde erstmals in der Version v0.11 eingeführt.

read_reply

syntax: res, err = red:read_reply()

Liest eine Antwort vom Redis-Server. Diese Methode ist hauptsächlich nützlich für die Redis Pub/Sub API, zum Beispiel,

    local cjson = require "cjson"
    local redis = require "resty.redis"

    local red = redis:new()
    local red2 = redis:new()

    red:set_timeouts(1000, 1000, 1000) -- 1 Sekunde
    red2:set_timeouts(1000, 1000, 1000) -- 1 Sekunde

    local ok, err = red:connect("127.0.0.1", 6379)
    if not ok then
        ngx.say("1: Verbindung fehlgeschlagen: ", err)
        return
    end

    ok, err = red2:connect("127.0.0.1", 6379)
    if not ok then
        ngx.say("2: Verbindung fehlgeschlagen: ", err)
        return
    end

    local res, err = red:subscribe("hund")
    if not res then
        ngx.say("1: Abonnieren fehlgeschlagen: ", err)
        return
    end

    ngx.say("1: abonnieren: ", cjson.encode(res))

    res, err = red2:publish("hund", "Hallo")
    if not res then
        ngx.say("2: Veröffentlichen fehlgeschlagen: ", err)
        return
    end

    ngx.say("2: veröffentlichen: ", cjson.encode(res))

    res, err = red:read_reply()
    if not res then
        ngx.say("1: Antwort lesen fehlgeschlagen: ", err)
        return
    end

    ngx.say("1: empfangen: ", cjson.encode(res))

    red:close()
    red2:close()

Wenn Sie dieses Beispiel ausführen, erhalten Sie eine Ausgabe wie diese:

1: abonnieren: ["subscribe","hund",1]
2: veröffentlichen: 1
1: empfangen: ["message","hund","Hallo"]

Die folgenden Klassenmethoden werden bereitgestellt:

add_commands

syntax: hash = redis.add_commands(cmd_name1, cmd_name2, ...)

WARNUNG Diese Methode ist jetzt veraltet, da wir bereits die automatische Lua-Methoden-Generierung für alle Redis-Befehle durchführen, die der Benutzer zu verwenden versucht, und wir daher diese nicht mehr benötigen.

Fügt neue Redis-Befehle zur resty.redis-Klasse hinzu. Hier ist ein Beispiel:

    local redis = require "resty.redis"

    redis.add_commands("foo", "bar")

    local red = redis:new()

    red:set_timeouts(1000, 1000, 1000) -- 1 Sekunde

    local ok, err = red:connect("127.0.0.1", 6379)
    if not ok then
        ngx.say("Verbindung fehlgeschlagen: ", err)
        return
    end

    local res, err = red:foo("a")
    if not res then
        ngx.say("Fehler bei foo: ", err)
    end

    res, err = red:bar()
    if not res then
        ngx.say("Fehler bei bar: ", err)
    end

Redis-Authentifizierung

Redis verwendet den AUTH-Befehl zur Authentifizierung: http://redis.io/commands/auth

Für diesen Befehl gibt es nichts Besonderes im Vergleich zu anderen Redis-Befehlen wie GET und SET. Man kann also einfach die auth-Methode auf Ihrer resty.redis-Instanz aufrufen. Hier ist ein Beispiel:

    local redis = require "resty.redis"
    local red = redis:new()

    red:set_timeouts(1000, 1000, 1000) -- 1 Sekunde

    local ok, err = red:connect("127.0.0.1", 6379)
    if not ok then
        ngx.say("Verbindung fehlgeschlagen: ", err)
        return
    end

    local res, err = red:auth("foobared")
    if not res then
        ngx.say("Authentifizierung fehlgeschlagen: ", err)
        return
    end

Dabei gehen wir davon aus, dass der Redis-Server mit dem Passwort foobared in der redis.conf-Datei konfiguriert ist:

requirepass foobared

Wenn das angegebene Passwort falsch ist, gibt das obige Beispiel Folgendes an den HTTP-Client aus:

Authentifizierung fehlgeschlagen: ERR ungültiges Passwort

Redis-Transaktionen

Diese Bibliothek unterstützt die Redis-Transaktionen. Hier ist ein Beispiel:

    local cjson = require "cjson"
    local redis = require "resty.redis"
    local red = redis:new()

    red:set_timeouts(1000, 1000, 1000) -- 1 Sekunde

    local ok, err = red:connect("127.0.0.1", 6379)
    if not ok then
        ngx.say("Verbindung fehlgeschlagen: ", err)
        return
    end

    local ok, err = red:multi()
    if not ok then
        ngx.say("Fehler beim Ausführen von multi: ", err)
        return
    end
    ngx.say("multi antwort: ", cjson.encode(ok))

    local ans, err = red:set("a", "abc")
    if not ans then
        ngx.say("Fehler beim Ausführen von sort: ", err)
        return
    end
    ngx.say("set antwort: ", cjson.encode(ans))

    local ans, err = red:lpop("a")
    if not ans then
        ngx.say("Fehler beim Ausführen von sort: ", err)
        return
    end
    ngx.say("set antwort: ", cjson.encode(ans))

    ans, err = red:exec()
    ngx.say("exec antwort: ", cjson.encode(ans))

    red:close()

Dann wird die Ausgabe sein:

multi antwort: "OK"
set antwort: "QUEUED"
set antwort: "QUEUED"
exec antwort: ["OK",[false,"ERR Operation gegen einen Schlüssel mit dem falschen Werttyp"]]

Redis-Modul

Diese Bibliothek unterstützt das Redis-Modul. Hier ist ein Beispiel mit dem RedisBloom-Modul:

    local cjson = require "cjson"
    local redis = require "resty.redis"
    -- registrieren Sie das Modulpräfix "bf" für RedisBloom
    redis.register_module_prefix("bf")

    local red = redis:new()

    local ok, err = red:connect("127.0.0.1", 6379)
    if not ok then
        ngx.say("Verbindung fehlgeschlagen: ", err)
        return
    end

    -- rufen Sie den BF.ADD-Befehl mit dem Präfix 'bf' auf
    res, err = red:bf():add("hund", 1)
    if not res then
        ngx.say(err)
        return
    end
    ngx.say("empfangen: ", cjson.encode(res))

    -- rufen Sie den BF.EXISTS-Befehl auf
    res, err = red:bf():exists("hund")
    if not res then
        ngx.say(err)
        return
    end
    ngx.say("empfangen: ", cjson.encode(res))

Lastenausgleich und Failover

Sie können Ihre eigene Redis-Lastenausgleichslogik in Lua ganz einfach implementieren. Halten Sie einfach eine Lua-Tabelle mit allen verfügbaren Redis-Backend-Informationen (wie Hostnamen und Portnummern) und wählen Sie einen Server gemäß einer Regel (wie Round-Robin oder schlüsselbasierte Hashing) aus der Lua-Tabelle bei jeder Anfrage aus. Sie können den aktuellen Regelstatus in den Daten Ihres eigenen Lua-Moduls verfolgen, siehe https://github.com/openresty/lua-nginx-module/#data-sharing-within-an-nginx-worker

Ähnlich können Sie eine automatische Failover-Logik in Lua mit großer Flexibilität implementieren.

Debugging

Es ist normalerweise praktisch, die lua-cjson-Bibliothek zu verwenden, um die Rückgabewerte der Redis-Befehlsmethoden in JSON zu kodieren. Zum Beispiel,

    local cjson = require "cjson"
    ...
    local res, err = red:mget("h1234", "h5678")
    if res then
        print("res: ", cjson.encode(res))
    end

Automatische Fehlerprotokollierung

Standardmäßig protokolliert das zugrunde liegende ngx_lua-Modul Fehler, wenn Socket-Fehler auftreten. Wenn Sie bereits eine ordnungsgemäße Fehlerbehandlung in Ihrem eigenen Lua-Code durchführen, wird empfohlen, diese automatische Fehlerprotokollierung zu deaktivieren, indem Sie die lua_socket_log_errors-Direktive von ngx_lua deaktivieren, das heißt,

    lua_socket_log_errors off;

Checkliste für Probleme

  1. Stellen Sie sicher, dass Sie die Größe des Verbindungspools richtig in der set_keepalive konfigurieren. Grundsätzlich, wenn Ihr Redis n gleichzeitige Verbindungen verarbeiten kann und Ihr NGINX m Worker hat, sollte die Größe des Verbindungspools als n/m konfiguriert werden. Zum Beispiel, wenn Ihr Redis normalerweise 1000 gleichzeitige Anfragen verarbeitet und Sie 10 NGINX-Worker haben, sollte die Größe des Verbindungspools 100 betragen. Ähnlich, wenn Sie p verschiedene NGINX-Instanzen haben, sollte die Größe des Verbindungspools n/m/p betragen.
  2. Stellen Sie sicher, dass die Backlog-Einstellung auf der Redis-Seite groß genug ist. Für Redis 2.8+ können Sie direkt den tcp-backlog-Parameter in der redis.conf-Datei anpassen (und auch den Kernelparameter SOMAXCONN entsprechend anpassen, mindestens unter Linux). Möglicherweise möchten Sie auch den maxclients-Parameter in der redis.conf anpassen.
  3. Stellen Sie sicher, dass Sie in den set_timeout- oder set_timeouts-Methoden keine zu kurzen Timeout-Einstellungen verwenden. Wenn Sie müssen, versuchen Sie, die Operation bei einer Zeitüberschreitung erneut durchzuführen und die automatische Fehlerprotokollierung auszuschalten (da Sie bereits eine ordnungsgemäße Fehlerbehandlung in Ihrem eigenen Lua-Code durchführen).
  4. Wenn die CPU-Auslastung Ihrer NGINX-Worker-Prozesse unter Last sehr hoch ist, könnte die NGINX-Ereignisschleife durch die CPU-Berechnung zu stark blockiert sein. Versuchen Sie, ein C-land on-CPU Flame Graph und ein Lua-land on-CPU Flame Graph für einen typischen NGINX-Worker-Prozess zu erstellen. Sie können die CPU-gebundenen Dinge gemäß diesen Flame Graphs optimieren.
  5. Wenn die CPU-Auslastung Ihrer NGINX-Worker-Prozesse unter Last sehr niedrig ist, könnte die NGINX-Ereignisschleife durch einige blockierende Systemaufrufe (wie Datei-I/O-Systemaufrufe) blockiert sein. Sie können das Problem bestätigen, indem Sie das epoll-loop-blocking-distr-Tool gegen einen typischen NGINX-Worker-Prozess ausführen. Wenn dies tatsächlich der Fall ist, können Sie weiter ein C-land off-CPU Flame Graph für einen NGINX-Worker-Prozess erstellen, um die tatsächlichen Blockierer zu analysieren.
  6. Wenn Ihr redis-server-Prozess nahe 100% CPU-Auslastung läuft, sollten Sie in Betracht ziehen, Ihr Redis-Backend auf mehrere Knoten zu skalieren oder das C-land on-CPU Flame Graph-Tool zu verwenden, um die internen Engpässe innerhalb des Redis-Serverprozesses zu analysieren.

Einschränkungen

  • Diese Bibliothek kann nicht in Codekontexten wie init_by_lua, set_by_lua, log_by_lua und header_filter_by_lua verwendet werden, in denen die ngx_lua-cosocket-API nicht verfügbar ist.
  • Die resty.redis-Objektinstanz kann nicht auf Modulebene in einer Lua-Variablen gespeichert werden, da sie dann von allen gleichzeitigen Anfragen, die vom selben NGINX-Worker-Prozess verarbeitet werden, geteilt wird (siehe https://github.com/openresty/lua-nginx-module/#data-sharing-within-an-nginx-worker) und zu schlechten Race-Bedingungen führen kann, wenn gleichzeitige Anfragen versuchen, dieselbe resty.redis-Instanz zu verwenden (Sie würden den "schlechten Antrag" oder "Socket beschäftigt"-Fehler von den Methodenaufrufen zurückbekommen). Sie sollten immer resty.redis-Objekte in lokalen Funktionsvariablen oder in der ngx.ctx-Tabelle initiieren. Diese Orte haben alle ihre eigenen Datenkopien für jede Anfrage.

Klonen Sie die neueste Version, angenommen v0.29

wget https://github.com/openresty/lua-resty-redis/archive/refs/tags/v0.29.tar.gz

Entpacken

tar -xvzf v0.29.tar.gz

In das Verzeichnis wechseln

cd lua-resty-redis-0.29

export LUA_LIB_DIR=/usr/local/openresty/site/lualib

Kompilieren und Installieren

make install

Jetzt wird der kompilierte Pfad ausgegeben

/usr/local/lib/lua/resty = lua_package_path in nginx conf

```

Siehe auch

GitHub

Sie finden möglicherweise zusätzliche Konfigurationstipps und Dokumentationen für dieses Modul im GitHub-Repository für nginx-module-redis.