Может ли redis конвейеризировать несколько команд, которые зависят от предыдущих?

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

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

Does valueX exist?
If it does insert valueY

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

Это возможно? Если это поможет, я использую Java, но не решил, какую клиентскую библиотеку (jedis или jredis, все еще тестирую). На самом деле я даже не полностью остановился на Redis, но очень сильно склоняюсь к нему (кажется, хорошо для того, что я делаю с точки зрения скорости), поэтому любые предложения приемлемы.


person Lostsoul    schedule 08.03.2012    source источник


Ответы (2)


Нет, на данный момент это невозможно осуществить. То, что вы ищете, — это функция, отсутствующая на данный момент, но она будет доступна в версии Redis 2.6. Это называется сценариями LUA. Вы можете выполнять серверные команды, которые зависят от предыдущих команд, все вместе, без необходимости получать их на клиенте. Подробнее см. здесь.

person hymloth    schedule 08.03.2012
comment
Большое спасибо за ваш ответ. Рад видеть его появление, но я действительно не хочу ждать, поэтому я подумал, могу ли я сам создать что-то подобное в своей программе. Вот логика, у меня есть метод, которому я отправлял пары значений поиска/записи, и он ставит запросы в очередь и запускает их в транзакции? Значит, остальная часть моей программы может продолжать работать, пока эта часть стоит в очереди? - person Lostsoul; 08.03.2012
comment
Вы можете передать пакет команд поиска, дождаться результатов, а затем передать несколько команд записи. Вы можете сделать это в отдельном потоке/процессе, чтобы не блокировать, пока не будут доступны результаты. - person hymloth; 08.03.2012

Redis не поддерживает это напрямую, но во многих случаях это очень часто требуется. Более обобщенный атомарный паттерн:

Check multiple conditions
If all satisfied, run multiple commands

Этого можно добиться с помощью простого сценария lua.

-- Validate conditions and exec commands if ok

local params = cjson.decode(ARGV[1])

-- Check conditions
for __, check in pairs(params["if"]) do
    if #check == 2 then
        if check[1] ~= redis.call(unpack(check[2])) then return 0 end
    elseif check[2] == "==" then
        if check[1] ~= redis.call(unpack(check[3])) then return 0 end
    elseif check[2] == "!=" then
        if check[1] == redis.call(unpack(check[3])) then return 0 end
    elseif check[2] == ">" then
        if check[1] <= redis.call(unpack(check[3])) then return 0 end
    elseif check[2] == "<" then
        if check[1] >= redis.call(unpack(check[3])) then return 0 end
    else
        error('invalid operator "'..tostring(check[2])..'" (expected "==", "!=", ">" or "<")')
    end
end

-- Eval redis commands
for __, exec in pairs(params["exec"]) do
    redis.call(unpack(exec))
end

return 1

Затем детали транзакции можно передать как простой JSON.stringify(object):

{
  // Conditions. All must be satisfied
  if: [
    [ 'initialized', '==', [ 'sget', 'custom-state' ] ]
  ],
  // Commands to execute if all conditions are satisfied
  exec: [
    [ 'set', 'custom-state', 'finished' ],
    [ 'incr', 'custom-counter' ]
  ]
}

Во многих случаях такие условные транзакции устраняют необходимость в написании пользовательских сценариев.

Дополнительные примеры/тесты/ источник

person Vitaly    schedule 19.02.2021