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

redis-util: Nginx-module-lua-resty-redis обертка утилит

Установка

Если вы еще не настроили подписку на 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-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

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

Этот документ описывает lua-resty-redis-util v0.7, выпущенный 15 декабря 2021 года.


Введение

Этот проект основан на [openresty/lua-resty-redis][] и является библиотекой для работы с Redis, разработанной [章亦春(agentzh)][agentzh] в openresty. Это утилита для вторичной обертки. Основные функции по-прежнему выполняются [openresty/lua-resty-redis][].

В этом документе предполагается, что вы уже знакомы с использованием lua-скриптов в nginx+lua или openresty (например, конфигурация lua_package_path, *_by_lua_file), основными знаниями о Redis и базовыми методами использования [openresty/lua-resty-redis][] ([openresty/lua-resty-redis#README.md][README.md]).

Установка

opm get anjia0532/lua-resty-redis-util

Сравнение

Приведем часть официального кода для объяснения

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

    red:set_timeout(1000) -- 1 сек -- установка времени ожидания

    local ok, err = red:connect("127.0.0.1", 6379) -- установка хоста и порта Redis
    if not ok then -- проверка на успешность подключения
        ngx.say("не удалось подключиться: ", err)
        return
    end

    ok, err = red:set("dog", "an animal") -- вставка ключа (аналог mysql insert)
    if not ok then -- проверка на успешность операции
        ngx.say("не удалось установить dog: ", err)
        return
    end

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

Если вы использовали Java, C# и другие объектно-ориентированные языки, вам может показаться, что такой подход слишком... требует рефакторинга, так как он раскрывает слишком много несущественных деталей, что приводит к большому количеству повторяющегося кода.

А теперь тот же самый контент, используя мой обернутый код. Скрыты операции по настройке пула соединений, получению соединений, возвращению соединений в пул и т.д.

    -- Зависимая библиотека
    local redis = require "resty.redis-util"
    -- Инициализация
    local red = redis:new();
    -- Вставка ключа
    local ok, err = red:set("dog", "an animal")
    -- Проверка результата
    if not ok then
      ngx.say("не удалось установить dog:", err)
      return
    end
    -- Вывод результата на страницу
    ngx.say("результат установки: ", ok) -- вывод результата на страницу

Важные моменты

Значения по умолчанию

local red = redis:new();
-- использованы значения по умолчанию, эквивалентно
local red2 = redis:new({
                            host='127.0.0.1',
                            port=6379,
                            db_index=0,
                            password=nil,
                            timeout=1000,
                            keepalive=60000,
                            pool_size=100
                        });
  • host: хост Redis, по умолчанию: 127.0.0.1
  • port: порт Redis, по умолчанию: 6379
  • db_index: индекс базы данных Redis (по умолчанию 0-15, всего 16 баз), по умолчанию используется база 0 (рекомендуется использовать разные порты для разных экземпляров или разные префиксы, так как для смены базы необходимо использовать команду select), по умолчанию: 0
  • password: пароль для аутентификации Redis
  • timeout: время ожидания подключения к Redis, по умолчанию: 1000 (1 секунда)
  • keepalive: максимальное время простоя пула соединений Redis, по умолчанию: 60000 (1 минута)
  • pool_size: размер пула соединений Redis, по умолчанию: 100

subscribe

Поскольку pub/sub не используется, реализованы только простые (un)subscribe, без дальнейшей реализации (un)psubscribe (подписка по шаблону), см. [Вторичная обертка интерфейса Redis (публикация и подписка)][linkRedis接口的二次封装(发布订阅)]

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

    -- Подписка на канал dog
    local func  = red:subscribe( "dog" )

    -- Проверка успешности подписки
    if not func then
      return nil
    end

    -- Получение значения
    local res, err = func() -- func()=func(true)
    -- Если не удалось, отменяем подписку
    if err then
        func(false)
    end

    -- Если получили результат, выводим на страницу
    if res then
        ngx.say("1: получено: ", cjson.encode(res))
    end

    -- Получаем снова
    res, err = func()

    -- После успешного получения, отменяем подписку func(false)
    if res then
        ngx.say("2: получено: ", cjson.encode(res))
        func(false)
    end

pipeline

См. [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("не удалось выполнить запрашиваемые операции в пайплайне: ", err)
        return
    else
        ngx.say("pipeline", cjson.encode(results))
    end
    -- вывод pipeline["OK","OK","Marry","Bob"]

script

См. [скрипт сжатия сложных запросов][linkScript压缩复杂请求]

    local red = redis:new();

    local id = 1
    local res, err = red:eval([[
        -- Обратите внимание, что при выполнении скрипта в Redis, значения, извлекаемые из KEYS/ARGV, имеют тип 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("не удалось получить информацию о группе: ", err)
       return
    end

    ngx.say("скрипт", res)

Благодарности

Этот инструмент заимствован из [lua-resty-redis/lib/resty/redis.lua][] и кода [Вторичной обертки интерфейса Redis][linkRedis接口的二次封装].

Обратная связь

Если у вас есть вопросы, пожалуйста, создайте [issues][].

GitHub

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