Приходилось ли реализовывать транзакции в Redis
Что проверяют
Знаете ли вы, что слово «транзакция» тут означает не то же, что в реляционной базе. Проверяют понимание отсутствия отката, смысла оптимистичной блокировки и того, когда вместо всего этого берут серверный скрипт.
Как отвечать
Скажите прямо: MULTI ставит команды в очередь, EXEC выполняет их подряд, и никто не вклинится. Это атомарность в смысле неделимости выполнения, но не откат. Команда, сломавшаяся при постановке в очередь, отменит всю пачку, а команда, упавшая уже во время выполнения, соседние не отменит: остальные применятся, а ошибка придёт отдельным элементом результата.
Дальше WATCH: он помечает ключи, и если между пометкой и EXEC их кто-то изменил, EXEC вернёт пустоту. Это оптимистичная блокировка, а значит нужен цикл повтора.
try (Jedis jedis = pool.getResource()) {
jedis.watch(key);
String current = jedis.get(key);
Transaction tx = jedis.multi();
tx.set(key, next(current));
if (tx.exec() == null) {
// ключ изменили, идём на новый круг
}
}Отдельно проговорите ограничение: внутри пачки читать и ветвиться нельзя, ответы приходят только после выполнения. Когда связка «прочитать, посчитать, записать» должна быть неделимой, берут скрипт на стороне сервера: он выполняется целиком, видит данные и возвращает результат. Отката у него тоже нет.
Где спотыкаются
Ждут поведения реляционной базы: раз вернулась ошибка, значит всё откатилось. Нет, часть команд уже применилась, и компенсацию придётся писать руками. Отсюда же попытки заворачивать в пачку операции, требующие отмены.
Теряют соединение. Пометка ключей, постановка команд и выполнение обязаны идти по одному соединению, а высокоуровневые обёртки берут его из пула на каждый вызов, и пометка уезжает в чужое соединение. Оптимистичная блокировка в таком коде не работает, причём молча. Забытый сброс пометки при выходе из цикла даёт ту же тишину.
Пробуют читать внутри пачки. Вызов возвращает не значение, а обещание, которое заполнится после выполнения, и код, сравнивающий его с чем-то на месте, всегда идёт по ветке пустоты. Ещё одна засада в кластере: ключи одной пачки должны попадать в один слот, иначе придёт отказ.