Pular para conteúdo

redis-util: Nginx-module-lua-resty-redis封装工具类

Instalação

Se você ainda não configurou a assinatura do repositório RPM, inscreva-se. Em seguida, você pode prosseguir com os seguintes passos.

CentOS/RHEL 7 ou 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-util

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-util

Para usar esta biblioteca Lua com NGINX, certifique-se de que o nginx-module-lua está instalado.

Este documento descreve lua-resty-redis-util v0.7 lançado em 15 de dezembro de 2021.


Introdução

Este projeto é baseado no [openresty/lua-resty-redis][] e é uma biblioteca desenvolvida por [章亦春(agentzh)][agentzh] para operações Redis no OpenResty. É uma biblioteca de ferramentas que encapsula a funcionalidade. A funcionalidade central ainda é realizada pelo [openresty/lua-resty-redis][].

Este documento assume que você já tem conhecimento sobre como usar scripts Lua com nginx+lua ou openresty (por exemplo, configuração lua_package_path, *_by_lua_file), conhecimento básico sobre Redis e o método básico de uso do [openresty/lua-resty-redis][] ([openresty/lua-resty-redis#README.md][README.md]).

Instalação

opm get anjia0532/lua-resty-redis-util

Comparação

Abaixo está um trecho de código oficial para referência:

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

    red:set_timeout(1000) -- 1 sec -- configura o tempo limite

    local ok, err = red:connect("127.0.0.1", 6379) -- configura o host e a porta do Redis
    if not ok then -- verifica se a conexão falhou
        ngx.say("falha ao conectar: ", err)
        return
    end

    ok, err = red:set("dog", "um animal") -- insere chave-valor (semelhante ao mysql insert)
    if not ok then -- verifica se a operação foi bem-sucedida
        ngx.say("falha ao definir dog: ", err)
        return
    end

    ngx.say("resultado da definição: ", ok) -- exibe o resultado na página
    -- coloca na piscina de conexões de tamanho 100,
    -- com 10 segundos de tempo máximo ocioso
    local ok, err = red:set_keepalive(10000, 100) -- coloca a conexão na piscina de conexões, 100 conexões, 10 segundos de tempo ocioso máximo
    if not ok then -- verifica o resultado da colocação na piscina
        ngx.say("falha ao definir keepalive: ", err)
        return
    end
    -- se não for colocar na piscina, e quiser fechar após o uso, use a seguinte escrita
    -- ou simplesmente feche a conexão imediatamente:
    -- local ok, err = red:close()
    -- if not ok then
    --     ngx.say("falha ao fechar: ", err)
    --     return
    -- end

Se você já usou Java, C# ou outras linguagens orientadas a objetos, pode achar essa forma de escrever muito... precisa ser reestruturada, expõe muitos detalhes irrelevantes, resultando em muito código repetido.

Abaixo está o mesmo conteúdo usando meu código encapsulado. Escondi operações como configurar a piscina de conexões, pegar conexões e devolver conexões após o uso.

    -- biblioteca dependente
    local redis = require "resty.redis-util"
    -- inicialização
    local red = redis:new();
    -- insere chave-valor
    local ok, err = red:set("dog", "um animal")
    -- verifica o resultado
    if not ok then
      ngx.say("falha ao definir dog:", err)
      return
    end
    -- exibe o resultado na página
    ngx.say("resultado da definição: ", ok) -- exibe o resultado na página

Observações

Valor Padrão

local red = redis:new();
-- usou valores padrão, equivalente a
local red2 = redis:new({
                            host='127.0.0.1',
                            port=6379,
                            db_index=0,
                            password=nil,
                            timeout=1000,
                            keepalive=60000,
                            pool_size=100
                        });
  • host: host do Redis, padrão: 127.0.0.1
  • port: porta do Redis, padrão: 6379
  • db_index: índice do banco de dados Redis (padrão 0-15, total de 16 bancos), o padrão é o banco 0 (recomenda-se usar portas diferentes para instâncias diferentes ou usar prefixos diferentes, pois mudar de banco requer o comando select), padrão: 0
  • password: senha de autenticação do Redis
  • timeout: tempo limite de conexão do Redis, padrão: 1000 (1s)
  • keepalive: tempo máximo ocioso da piscina de conexões do Redis, padrão: 60000 (1m)
  • pool_size: tamanho da piscina de conexões do Redis, padrão: 100

subscribe

Como não foi utilizado pub/sub, apenas foi implementado de forma simples (un)subscribe, sem continuar a implementação de (un)psubscribe (assinatura de padrão), consulte [Redis 接口的二次封装(发布订阅)][linkRedis接口的二次封装(发布订阅)]

    local cjson = require "cjson"
    local red = redis:new();

    -- assina o canal dog
    local func  = red:subscribe("dog")

    -- verifica se a assinatura foi bem-sucedida
    if not func then
      return nil
    end

    -- obtém o valor
    local res, err = func() -- func()=func(true)
    -- se falhar, cancela a assinatura
    if err then
        func(false)
    end

    -- se obtiver resultado, exibe na página
    if res then
        ngx.say("1: recebido: ", cjson.encode(res))
    end

    -- obtém novamente
    res, err = func()

    -- após obter com sucesso, cancela a assinatura func(false)
    if res then
        ngx.say("2: recebido: ", cjson.encode(res))
        func(false)
    end

pipeline

Consulte [openresty/lua-resty-redis#Synopsis][]

    local cjson = require "cjson"
    local red = redis:new();

    red:init_pipeline()

    red:set("cat", "Marry")
    red:set("horse", "Bob")
    red:get("cat")
    red:get("horse")

    local results, err = red:commit_pipeline()

    if not results then
        ngx.say("falha ao confirmar as requisições em pipeline: ", err)
        return
    else
        ngx.say("pipeline", cjson.encode(results))
    end
    -- saída pipeline["OK","OK","Marry","Bob"]

script

Consulte [script 压缩复杂请求][linkScript压缩复杂请求]

    local red = redis:new();

    local id = 1
    local res, err = red:eval([[
        -- Note que ao executar scripts no Redis, os valores obtidos de KEYS/ARGV são do tipo string
        local info = redis.call('get', KEYS[1])
        info = cjson.decode(info)
        local g_id = info.gid

        local g_info = redis.call('get', g_id)
        return g_info
        ]], 1, id)

    if not res then
       ngx.say("falha ao obter as informações do grupo: ", err)
       return
    end

    ngx.say("script", res)

Agradecimentos

Esta ferramenta se baseou no código do [lua-resty-redis/lib/resty/redis.lua][] e na [Redis 接口的二次封装][linkRedis接口的二次封装].

Feedback

Se você tiver alguma dúvida, sinta-se à vontade para abrir [issues][].

GitHub

Você pode encontrar dicas adicionais de configuração e documentação para este módulo no repositório GitHub para nginx-module-redis-util.