Перейти к содержанию

memcached: Драйвер клиента Lua memcached для nginx-module-lua на основе API cosocket

Установка

Если вы еще не подписались на репозиторий RPM, зарегистрируйтесь. Затем вы можете перейти к следующим шагам.

CentOS/RHEL 7 или 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

Чтобы использовать эту библиотеку Lua с NGINX, убедитесь, что nginx-module-lua установлен.

Этот документ описывает lua-resty-memcached v0.17, выпущенную 19 января 2023 года.


Эта библиотека Lua является драйвером клиента memcached для модуля ngx_lua nginx:

http://wiki.nginx.org/HttpLuaModule

Эта библиотека Lua использует API cosocket ngx_lua, который обеспечивает 100% неблокирующее поведение.

Обратите внимание, что требуется как минимум ngx_lua 0.5.0rc29 или OpenResty 1.0.15.7.

Синопсис

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

                memc:set_timeout(1000) -- 1 sec

                -- или подключитесь к файлу сокета unix,
                -- который прослушивается сервером memcached:
                --     local ok, err = memc:connect("unix:/path/to/memc.sock")

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

                local ok, err = memc:flush_all()
                if not ok then
                    ngx.say("failed to flush all: ", err)
                    return
                end

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

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

                if not res then
                    ngx.say("dog not found")
                    return
                end

                ngx.say("dog: ", res)

                -- поместите его в пул соединений размером 100,
                -- с максимальным временем простоя 10 секунд
                local ok, err = memc:set_keepalive(10000, 100)
                if not ok then
                    ngx.say("cannot set keepalive: ", err)
                    return
                end

                -- или просто закройте соединение сразу:
                -- local ok, err = memc:close()
                -- if not ok then
                --     ngx.say("failed to close: ", err)
                --     return
                -- end
            ';
        }
    }

Методы

Аргумент key, предоставленный в следующих методах, будет автоматически экранирован в соответствии с правилами экранирования URI перед отправкой на сервер memcached.

new

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

Создает объект memcached. В случае неудачи возвращает nil и строку, описывающую ошибку.

Принимает необязательный аргумент opts в виде таблицы. Поддерживаются следующие параметры:

  • key_transform

    массив таблиц, содержащий две функции для экранирования и декодирования ключей memcached соответственно. По умолчанию ключи memcached будут экранированы и декодированы как компоненты URI, то есть

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

connect

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

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

Пытается подключиться к удаленному хосту и порту, на которых прослушивается сервер memcached, или к локальному файлу сокета unix, который прослушивается сервером memcached.

Перед тем как фактически разрешить имя хоста и подключиться к удаленному бэкенду, этот метод всегда будет искать в пуле соединений подходящие неактивные соединения, созданные предыдущими вызовами этого метода.

sslhandshake

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

Выполняет SSL/TLS рукопожатие на текущем установленном соединении. См. API tcpsock.sslhandshake от OpenResty для получения дополнительных сведений.

set

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

Вставляет запись в memcached без условий. Если ключ уже существует, он будет переопределен.

Аргумент value также может быть таблицей Lua, содержащей несколько строк Lua, которые должны быть объединены в одно целое (без каких-либо разделителей). Например,

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

функционально эквивалентно

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

Параметр exptime является необязательным и по умолчанию равен 0 (что означает, что никогда не истекает). Время истечения указывается в секундах.

Параметр flags является необязательным и по умолчанию равен 0.

set_timeout

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

Устанавливает защиту по времени ожидания (в мс) для последующих операций, включая метод connect.

Возвращает 1 при успешном выполнении и nil плюс строку, описывающую ошибку в противном случае.

set_timeouts

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

Устанавливает тайм-ауты (в мс) для операций подключения, отправки и чтения соответственно.

Возвращает 1 при успешном выполнении и nil плюс строку, описывающую ошибку в противном случае.

set_keepalive

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

Сразу помещает текущее соединение memcached в пул соединений ngx_lua.

Вы можете указать максимальное время простоя (в мс), когда соединение находится в пуле, и максимальный размер пула для каждого рабочего процесса nginx.

В случае успеха возвращает 1. В случае ошибок возвращает nil с строкой, описывающей ошибку.

Вызывайте этот метод только в том месте, где вы бы вызвали метод close. Вызов этого метода немедленно переведет текущий объект memcached в состояние closed. Любые последующие операции, кроме connect(), на текущем объекте будут возвращать ошибку closed.

get_reused_times

syntax: times, err = memc:get_reused_times()

Этот метод возвращает количество (успешно) повторно использованных раз для текущего соединения. В случае ошибки возвращает nil и строку, описывающую ошибку.

Если текущее соединение не поступает из встроенного пула соединений, то этот метод всегда возвращает 0, то есть соединение никогда не использовалось повторно (пока). Если соединение поступает из пула соединений, то возвращаемое значение всегда ненулевое. Таким образом, этот метод также можно использовать для определения, поступает ли текущее соединение из пула.

close

syntax: ok, err = memc:close()

Закрывает текущее соединение memcached и возвращает статус.

В случае успеха возвращает 1. В случае ошибок возвращает nil с строкой, описывающей ошибку.

add

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

Вставляет запись в memcached, если и только если ключ не существует.

Аргумент value также может быть таблицей Lua, содержащей несколько строк Lua, которые должны быть объединены в одно целое (без каких-либо разделителей). Например,

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

функционально эквивалентно

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

Параметр exptime является необязательным и по умолчанию равен 0 (что означает, что никогда не истекает). Время истечения указывается в секундах.

Параметр flags является необязательным, по умолчанию равен 0.

В случае успеха возвращает 1. В случае ошибок возвращает nil с строкой, описывающей ошибку.

replace

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

Вставляет запись в memcached, если и только если ключ существует.

Аргумент value также может быть таблицей Lua, содержащей несколько строк Lua, которые должны быть объединены в одно целое (без каких-либо разделителей). Например,

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

функционально эквивалентно

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

Параметр exptime является необязательным и по умолчанию равен 0 (что означает, что никогда не истекает). Время истечения указывается в секундах.

Параметр flags является необязательным, по умолчанию равен 0.

В случае успеха возвращает 1. В случае ошибок возвращает nil с строкой, описывающей ошибку.

append

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

Добавляет значение к записи с тем же ключом, которая уже существует в memcached.

Аргумент value также может быть таблицей Lua, содержащей несколько строк Lua, которые должны быть объединены в одно целое (без каких-либо разделителей). Например,

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

функционально эквивалентно

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

Параметр exptime является необязательным и по умолчанию равен 0 (что означает, что никогда не истекает). Время истечения указывается в секундах.

Параметр flags является необязательным, по умолчанию равен 0.

В случае успеха возвращает 1. В случае ошибок возвращает nil с строкой, описывающей ошибку.

prepend

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

Добавляет значение к записи с тем же ключом, которая уже существует в memcached.

Аргумент value также может быть таблицей Lua, содержащей несколько строк Lua, которые должны быть объединены в одно целое (без каких-либо разделителей). Например,

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

функционально эквивалентно

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

Параметр exptime является необязательным и по умолчанию равен 0 (что означает, что никогда не истекает). Время истечения указывается в секундах.

Параметр flags является необязательным, по умолчанию равен 0.

В случае успеха возвращает 1. В случае ошибок возвращает nil с строкой, описывающей ошибку.

get

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

Получает одну запись или несколько записей на сервере memcached через один ключ или таблицу ключей.

Сначала обсудим случай, когда ключ — это одна строка.

Значение ключа и связанное значение флагов будут возвращены, если запись найдена и не произошло ошибок.

В случае ошибок значения nil будут возвращены для value и flags, а также будет возвращено третье (строковое) значение для описания ошибки.

Если запись не найдена, то будут возвращены три значения nil.

Теперь обсудим случай, когда предоставляется таблица Lua с несколькими ключами.

В этом случае всегда будет возвращаться таблица Lua, содержащая пары ключ-результат в случае успеха. Каждое значение, соответствующее каждому ключу в таблице, также является таблицей, содержащей два значения: значение ключа и флаги ключа. Если ключ не существует, то в таблице results нет соответствующих записей.

В случае ошибок будет возвращено nil, а второе возвращаемое значение будет строкой, описывающей ошибку.

gets

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

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

Так же, как и метод get, но также будет возвращено уникальное значение CAS, связанное с записью, в дополнение к значению ключа и флагам.

Этот метод обычно используется вместе с методом cas.

cas

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

Так же, как и метод set, но выполняет операцию проверки и установки, что означает "сохранить эти данные, но только если никто другой не обновил их с тех пор, как я их последний раз получал".

Аргумент cas_unique можно получить из метода gets.

touch

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

Обновляет время истечения существующего ключа.

Возвращает 1 при успехе или nil с строкой, описывающей ошибку в противном случае.

Этот метод был впервые представлен в релизе v0.11.

flush_all

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

Немедленно очищает (или аннулирует) все существующие записи на сервере memcached (по умолчанию) или после истечения времени, указанного аргументом time (в секундах).

В случае успеха возвращает 1. В случае ошибок возвращает nil с строкой, описывающей ошибку.

delete

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

Немедленно удаляет ключ из memcached.

Ключ, который нужно удалить, должен уже существовать в memcached.

В случае успеха возвращает 1. В случае ошибок возвращает nil с строкой, описывающей ошибку.

incr

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

Увеличивает значение указанного ключа на целочисленное значение, указанное в аргументе delta.

Возвращает новое значение после увеличения в случае успеха и nil с строкой, описывающей ошибку в случае неудачи.

decr

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

Уменьшает значение указанного ключа на целочисленное значение, указанное в аргументе delta.

Возвращает новое значение после уменьшения в случае успеха и nil с строкой, описывающей ошибку в случае неудачи.

stats

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

Возвращает информацию о статистике сервера memcached с необязательным аргументом args.

В случае успеха этот метод возвращает таблицу lua, содержащую все строки вывода; в случае неудачи возвращает nil с строкой, описывающей ошибку.

Если аргумент args опущен, возвращается общая статистика сервера. Возможные значения аргумента args включают items, sizes, slabs и другие.

quit

syntax: ok, err = memc:quit()

Сообщает серверу закрыть текущее соединение memcached.

Возвращает 1 в случае успеха и nil в противном случае. В случае ошибок будет возвращено еще одно строковое значение для описания ошибки.

В общем, вы можете просто вызвать метод close, чтобы достичь того же эффекта.

verbosity

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

Устанавливает уровень подробности, используемый сервером memcached. Аргумент level должен быть указан только в целых числах.

Возвращает 1 в случае успеха и nil в противном случае. В случае ошибок будет возвращено еще одно строковое значение для описания ошибки.

init_pipeline

syntax: err = memc:init_pipeline(n?)

Включает режим конвейеризации Memcache. Все последующие вызовы методов команд Memcache будут автоматически буферизоваться и отправляться на сервер за один раз, когда будет вызван метод commit_pipeline, или отменяться при вызове метода cancel_pipeline.

Необязательный параметр n — это размер буферных таблиц. Значение по умолчанию — 4.

commit_pipeline

syntax: results, err = memc:commit_pipeline()

Выходит из режима конвейеризации, подтверждая все кэшированные запросы Memcache на удаленный сервер за один раз. Все ответы на эти запросы будут автоматически собраны и возвращены как если бы это был большой многообъемный ответ на высшем уровне.

Этот метод успешно возвращает таблицу lua. В случае неудачи возвращает строку lua, описывающую ошибку.

cancel_pipeline

syntax: memc:cancel_pipeline()

Выходит из режима конвейеризации, отказываясь от всех существующих буферных команд Memcache с момента последнего вызова метода init_pipeline.

Метод ничего не возвращает. Всегда выполняется успешно.

Автоматическая регистрация ошибок

По умолчанию основной модуль ngx_lua выполняет регистрацию ошибок, когда происходят ошибки сокета. Если вы уже выполняете правильную обработку ошибок в своем собственном коде Lua, то рекомендуется отключить эту автоматическую регистрацию ошибок, отключив директиву lua_socket_log_errors модуля ngx_lua, то есть,

    lua_socket_log_errors off;

Ограничения

  • Эта библиотека не может использоваться в контекстах кода, таких как set_by_lua*, log_by_lua* и header_filter_by_lua*, где API cosocket ngx_lua недоступен.
  • Экземпляр объекта resty.memcached не может храниться в переменной Lua на уровне модуля Lua, потому что он будет разделяться всеми параллельными запросами, обрабатываемыми тем же рабочим процессом nginx (см. http://wiki.nginx.org/HttpLuaModule#Data_Sharing_within_an_Nginx_Worker) и приведет к плохим условиям гонки, когда параллельные запросы пытаются использовать один и тот же экземпляр resty.memcached. Вы всегда должны инициализировать объекты resty.memcached в локальных переменных функции или в таблице ngx.ctx. Эти места имеют свои собственные копии данных для каждого запроса.

См. также

GitHub

Вы можете найти дополнительные советы по конфигурации и документацию для этого модуля в репозитории GitHub для nginx-module-memcached.