Redis: установить, если существует - через python

У меня есть огромный список ключей и одно значение (одинаковое для всех ключей), которое должно быть записано в экземпляр Redis. Это должно происходить только в том случае, если запись с этим ключом уже существует.

Существует команда MSETNX, которая делает обратное: вставляет запись, когда ключ делает НЕ существует.

Конечно, я могу просто проверить перед этим через EXIST и установить его в зависимости от результата, но как мне убедиться, что этот атомный. И поскольку этот список может быть очень большим, как мне сделать это на основе конвейера?

я использую redis-py в качестве оболочки, и на сервере нет поддержки Lua-Scripting .


person kraiz    schedule 06.08.2012    source источник
comment
Используйте SETNX для создания блокировок. Это сделает все ваши операции атомарными.   -  person freakish    schedule 06.08.2012


Ответы (1)


Это не очень удобно делать без Lua, но все же можно сделать с помощью команд WATCH/MULTI/EXEC. Идея состоит в том, чтобы разбить ваш огромный список ключей на блоки по n элементов (например, n=20), а затем применить к каждому блоку следующую функцию:

def process_block( redis_client, block, value ):
    with redis_client.pipeline() as pipe:
        while True:
            try:
                pipe.watch( block )
                to_set = [ for x in block if pipe.exists(x) ]
                if to_set:
                    pipe.multi()
                    for x in to_set:
                        pipe.set( x, value )
                    pipe.execute()
                break
            except redis.WatchError:
                continue
            finally:
                pipe.reset()

Атомарность гарантируется командами WATCH/MULTI/EXEC, и вы будете конвейеризировать 1 команду WATCH, 1 MULTI, до n команд SET и 1 команду EXEC. Однако вы будете платить за поездки EXISTS туда и обратно. Выбор правильного значения n — это компромисс между фактором конвейеризации и риском параллельных взаимодействий. Его не следует устанавливать слишком высоко.

person Didier Spezia    schedule 06.08.2012
comment
не то, что я ожидал, но пока я не хочу обновляться, я попробую. спасибо! - person kraiz; 06.08.2012