Pular para conteúdo

memcached: driver de cliente Lua memcached para nginx-module-lua baseado na API cosocket

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

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

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

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

Este documento descreve lua-resty-memcached v0.17 lançado em 19 de janeiro de 2023.


Esta biblioteca Lua é um driver de cliente memcached para o módulo ngx_lua do nginx:

http://wiki.nginx.org/HttpLuaModule

Esta biblioteca Lua aproveita a API cosocket do ngx_lua, que garante um comportamento 100% não bloqueante.

Observe que pelo menos ngx_lua 0.5.0rc29 ou OpenResty 1.0.15.7 é necessário.

Sinopse

    server {
        location /test {
            content_by_lua '
                local memcached = require "resty.memcached"
                local memc, err = memcached:new()
                if not memc then
                    ngx.say("falha ao instanciar memc: ", err)
                    return
                end

                memc:set_timeout(1000) -- 1 seg

                -- ou conecte-se a um arquivo de socket de domínio unix escutado
                -- por um servidor memcached:
                --     local ok, err = memc:connect("unix:/caminho/para/memc.sock")

                local ok, err = memc:connect("127.0.0.1", 11211)
                if not ok then
                    ngx.say("falha ao conectar: ", err)
                    return
                end

                local ok, err = memc:flush_all()
                if not ok then
                    ngx.say("falha ao limpar tudo: ", err)
                    return
                end

                local ok, err = memc:set("dog", 32)
                if not ok then
                    ngx.say("falha ao definir dog: ", err)
                    return
                end

                local res, flags, err = memc:get("dog")
                if err then
                    ngx.say("falha ao obter dog: ", err)
                    return
                end

                if not res then
                    ngx.say("dog não encontrado")
                    return
                end

                ngx.say("dog: ", res)

                -- coloque-o no pool de conexões de tamanho 100,
                -- com 10 segundos de tempo máximo ocioso
                local ok, err = memc:set_keepalive(10000, 100)
                if not ok then
                    ngx.say("não é possível definir keepalive: ", err)
                    return
                end

                -- ou simplesmente feche a conexão imediatamente:
                -- local ok, err = memc:close()
                -- if not ok then
                --     ngx.say("falha ao fechar: ", err)
                --     return
                -- end
            ';
        }
    }

Métodos

O argumento key fornecido nos seguintes métodos será automaticamente escapado de acordo com as regras de escape de URI antes de ser enviado ao servidor memcached.

new

syntax: memc, err = memcached:new(opts?)

Cria um objeto memcached. Em caso de falhas, retorna nil e uma string descrevendo o erro.

Aceita um argumento opcional de tabela opts. As seguintes opções são suportadas:

  • key_transform

    uma tabela de array contendo duas funções para escapar e desescapar as chaves do memcached, respectivamente. Por padrão, as chaves do memcached serão escapadas e desescapadas como componentes de URI, ou seja,

    memcached:new{
        key_transform = { ngx.escape_uri, ngx.unescape_uri }
    }

connect

syntax: ok, err = memc:connect(host, port)

syntax: ok, err = memc:connect("unix:/caminho/para/unix.sock")

Tenta conectar ao host remoto e à porta que o servidor memcached está escutando ou a um arquivo de socket de domínio unix local escutado pelo servidor memcached.

Antes de realmente resolver o nome do host e conectar ao backend remoto, este método sempre procurará no pool de conexões por conexões ociosas correspondentes criadas por chamadas anteriores deste método.

sslhandshake

syntax: session, err = memc:sslhandshake(reused_session?, server_name?, ssl_verify?, send_status_req?)

Realiza o handshake SSL/TLS na conexão atualmente estabelecida. Consulte a tcpsock.sslhandshake API do OpenResty para mais detalhes.

set

syntax: ok, err = memc:set(key, value, exptime, flags)

Insere uma entrada no memcached incondicionalmente. Se a chave já existir, sobrescreve-a.

O argumento value também pode ser uma tabela Lua contendo várias strings Lua que devem ser concatenadas como um todo (sem quaisquer delimitadores). Por exemplo,

    memc:set("dog", {"a ", {"kind of"}, " animal"})

é funcionalmente equivalente a

    memc:set("dog", "a kind of animal")

O parâmetro exptime é opcional e tem como padrão 0 (significando que nunca expira). O tempo de expiração está em segundos.

O parâmetro flags é opcional e tem como padrão 0.

set_timeout

syntax: ok, err = memc:set_timeout(timeout)

Define o tempo limite (em ms) de proteção para operações subsequentes, incluindo o método connect.

Retorna 1 quando bem-sucedido e nil mais uma string descrevendo o erro, caso contrário.

set_timeouts

syntax: ok, err = memc:set_timeouts(connect_timeout, send_timeout, read_timeout)

Define os tempos limites (em ms) para operações de conexão, envio e leitura, respectivamente.

Retorna 1 quando bem-sucedido e nil mais uma string descrevendo o erro, caso contrário.

set_keepalive

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

Coloca a conexão memcached atual imediatamente no pool de conexões cosocket do ngx_lua.

Você pode especificar o tempo máximo ocioso (em ms) quando a conexão está no pool e o tamanho máximo do pool para cada processo trabalhador do nginx.

Em caso de sucesso, retorna 1. Em caso de erros, retorna nil com uma string descrevendo o erro.

Chame este método apenas no lugar onde você chamaria o método close. Chamar este método transformará imediatamente o objeto memcached atual no estado closed. Quaisquer operações subsequentes, além de connect() no objeto atual, retornarão o erro closed.

get_reused_times

syntax: times, err = memc:get_reused_times()

Este método retorna o número de vezes que a conexão atual foi (com sucesso) reutilizada. Em caso de erro, retorna nil e uma string descrevendo o erro.

Se a conexão atual não vier do pool de conexões embutido, então este método sempre retornará 0, ou seja, a conexão nunca foi reutilizada (ainda). Se a conexão vier do pool de conexões, então o valor de retorno será sempre diferente de zero. Portanto, este método também pode ser usado para determinar se a conexão atual vem do pool.

close

syntax: ok, err = memc:close()

Fecha a conexão memcached atual e retorna o status.

Em caso de sucesso, retorna 1. Em caso de erros, retorna nil com uma string descrevendo o erro.

add

syntax: ok, err = memc:add(key, value, exptime, flags)

Insere uma entrada no memcached se e somente se a chave não existir.

O argumento value também pode ser uma tabela Lua contendo várias strings Lua que devem ser concatenadas como um todo (sem quaisquer delimitadores). Por exemplo,

    memc:add("dog", {"a ", {"kind of"}, " animal"})

é funcionalmente equivalente a

    memc:add("dog", "a kind of animal")

O parâmetro exptime é opcional e tem como padrão 0 (significando que nunca expira). O tempo de expiração está em segundos.

O parâmetro flags é opcional, com padrão 0.

Em caso de sucesso, retorna 1. Em caso de erros, retorna nil com uma string descrevendo o erro.

replace

syntax: ok, err = memc:replace(key, value, exptime, flags)

Insere uma entrada no memcached se e somente se a chave já existir.

O argumento value também pode ser uma tabela Lua contendo várias strings Lua que devem ser concatenadas como um todo (sem quaisquer delimitadores). Por exemplo,

    memc:replace("dog", {"a ", {"kind of"}, " animal"})

é funcionalmente equivalente a

    memc:replace("dog", "a kind of animal")

O parâmetro exptime é opcional e tem como padrão 0 (significando que nunca expira). O tempo de expiração está em segundos.

O parâmetro flags é opcional, com padrão 0.

Em caso de sucesso, retorna 1. Em caso de erros, retorna nil com uma string descrevendo o erro.

append

syntax: ok, err = memc:append(key, value, exptime, flags)

Anexa o valor a uma entrada com a mesma chave que já existe no memcached.

O argumento value também pode ser uma tabela Lua contendo várias strings Lua que devem ser concatenadas como um todo (sem quaisquer delimitadores). Por exemplo,

    memc:append("dog", {"a ", {"kind of"}, " animal"})

é funcionalmente equivalente a

    memc:append("dog", "a kind of animal")

O parâmetro exptime é opcional e tem como padrão 0 (significando que nunca expira). O tempo de expiração está em segundos.

O parâmetro flags é opcional, com padrão 0.

Em caso de sucesso, retorna 1. Em caso de erros, retorna nil com uma string descrevendo o erro.

prepend

syntax: ok, err = memc:prepend(key, value, exptime, flags)

Precede o valor a uma entrada com a mesma chave que já existe no memcached.

O argumento value também pode ser uma tabela Lua contendo várias strings Lua que devem ser concatenadas como um todo (sem quaisquer delimitadores). Por exemplo,

    memc:prepend("dog", {"a ", {"kind of"}, " animal"})

é funcionalmente equivalente a

    memc:prepend("dog", "a kind of animal")

O parâmetro exptime é opcional e tem como padrão 0 (significando que nunca expira). O tempo de expiração está em segundos.

O parâmetro flags é opcional e tem como padrão 0.

Em caso de sucesso, retorna 1. Em caso de erros, retorna nil com uma string descrevendo o erro.

get

syntax: value, flags, err = memc:get(key) syntax: results, err = memc:get(keys)

Obtém uma única entrada ou várias entradas no servidor memcached via uma única chave ou uma tabela de chaves.

Vamos primeiro discutir o caso em que a chave é uma única string.

O valor da chave e o valor de flags associados serão retornados se a entrada for encontrada e nenhum erro ocorrer.

Em caso de erros, os valores nil serão retornados para value e flags e um terceiro valor (string) também será retornado para descrever o erro.

Se a entrada não for encontrada, então três valores nil serão retornados.

Agora vamos discutir o caso em que uma tabela Lua de várias chaves é fornecida.

Neste caso, uma tabela Lua contendo os pares chave-resultado será sempre retornada em caso de sucesso. Cada valor correspondente a cada chave na tabela também é uma tabela contendo dois valores, o valor da chave e as flags da chave. Se uma chave não existir, então não haverá entradas correspondentes na tabela results.

Em caso de erros, nil será retornado e o segundo valor de retorno será uma string descrevendo o erro.

gets

syntax: value, flags, cas_unique, err = memc:gets(key)

syntax: results, err = memc:gets(keys)

Assim como o método get, mas também retornará o valor CAS único associado à entrada, além do valor da chave e das flags.

Este método é geralmente usado em conjunto com o método cas.

cas

syntax: ok, err = memc:cas(key, value, cas_unique, exptime?, flags?)

Assim como o método set, mas realiza uma operação de verificação e definição, o que significa "armazenar esses dados, mas apenas se ninguém mais tiver atualizado desde a última vez que eu os busquei."

O argumento cas_unique pode ser obtido do método gets.

touch

syntax: ok, err = memc:touch(key, exptime)

Atualiza o tempo de expiração de uma chave existente.

Retorna 1 em caso de sucesso ou nil com uma string descrevendo o erro, caso contrário.

Este método foi introduzido pela primeira vez na versão v0.11.

flush_all

syntax: ok, err = memc:flush_all(time?)

Limpa (ou invalida) todas as entradas existentes no servidor memcached imediatamente (por padrão) ou após a expiração especificada pelo argumento time (em segundos).

Em caso de sucesso, retorna 1. Em caso de erros, retorna nil com uma string descrevendo o erro.

delete

syntax: ok, err = memc:delete(key)

Exclui a chave do memcached imediatamente.

A chave a ser excluída deve já existir no memcached.

Em caso de sucesso, retorna 1. Em caso de erros, retorna nil com uma string descrevendo o erro.

incr

syntax: new_value, err = memc:incr(key, delta)

Incrementa o valor da chave especificada pelo valor inteiro especificado no argumento delta.

Retorna o novo valor após a incrementação em caso de sucesso, e nil com uma string descrevendo o erro em caso de falhas.

decr

syntax: new_value, err = memc:decr(key, value)

Decrementa o valor da chave especificada pelo valor inteiro especificado no argumento delta.

Retorna o novo valor após a decrementação em caso de sucesso, e nil com uma string descrevendo o erro em caso de falhas.

stats

syntax: lines, err = memc:stats(args?)

Retorna informações de estatísticas do servidor memcached com um argumento opcional args.

Em caso de sucesso, este método retorna uma tabela Lua contendo todas as linhas da saída; em caso de falhas, retorna nil com uma string descrevendo o erro.

Se o argumento args for omitido, estatísticas gerais do servidor são retornadas. Os possíveis valores do argumento args são items, sizes, slabs, entre outros.

quit

syntax: ok, err = memc:quit()

Informa ao servidor para fechar a conexão memcached atual.

Retorna 1 em caso de sucesso e nil caso contrário. Em caso de falhas, outro valor de string também será retornado para descrever o erro.

Geralmente, você pode simplesmente chamar diretamente o método close para alcançar o mesmo efeito.

verbosity

syntax: ok, err = memc:verbosity(level)

Define o nível de verbosidade usado pelo servidor memcached. O argumento level deve ser fornecido apenas como inteiros.

Retorna 1 em caso de sucesso e nil caso contrário. Em caso de falhas, outro valor de string também será retornado para descrever o erro.

init_pipeline

syntax: err = memc:init_pipeline(n?)

Habilita o modo de pipeline do Memcache. Todas as chamadas subsequentes aos métodos de comando do Memcache serão automaticamente armazenadas em buffer e enviadas ao servidor em uma única execução quando o método commit_pipeline for chamado ou canceladas chamando o método cancel_pipeline.

O parâmetro opcional n é o tamanho das tabelas de buffer. valor padrão 4

commit_pipeline

syntax: results, err = memc:commit_pipeline()

Sai do modo de pipeline comprometendo todas as consultas Memcache em cache para o servidor remoto em uma única execução. Todas as respostas para essas consultas serão coletadas automaticamente e retornadas como se fossem uma grande resposta multi-bulk no nível mais alto.

Este método retorna uma tabela Lua em caso de sucesso. Retorna uma string Lua descrevendo o erro em caso de falhas.

cancel_pipeline

syntax: memc:cancel_pipeline()

Sai do modo de pipeline descartando todos os comandos Memcache em buffer existentes desde a última chamada ao método init_pipeline.

o método não retorna. sempre tem sucesso.

Registro Automático de Erros

Por padrão, o módulo subjacente ngx_lua faz registro de erros quando ocorrem erros de socket. Se você já está fazendo um tratamento de erros adequado em seu próprio código Lua, então é recomendado desativar este registro automático de erros desativando a diretiva lua_socket_log_errors do ngx_lua, ou seja,

    lua_socket_log_errors off;

Limitações

  • Esta biblioteca não pode ser usada em contextos de código como set_by_lua*, log_by_lua*, e header_filter_by_lua* onde a API cosocket do ngx_lua não está disponível.
  • A instância do objeto resty.memcached não pode ser armazenada em uma variável Lua no nível do módulo Lua, porque então será compartilhada por todas as requisições concorrentes tratadas pelo mesmo processo trabalhador do nginx (veja http://wiki.nginx.org/HttpLuaModule#Data_Sharing_within_an_Nginx_Worker) e resultará em más condições de corrida quando requisições concorrentes tentarem usar a mesma instância resty.memcached. Você deve sempre iniciar objetos resty.memcached em variáveis locais de função ou na tabela ngx.ctx. Esses lugares têm suas próprias cópias de dados para cada requisição.

Veja Também

GitHub

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