#ruby #redis
#ruby #redis
Вопрос:
При использовании redis-rb в приложении Rails не работает следующее:
irb> keys = $redis.keys("autocomplete*")
=> ["autocomplete_foo", "autocomplete_bar", "autocomplete_bat"]
irb> $redis.del(keys)
=> 0
Это работает нормально:
irb> $redis.del("autocomplete_foo", "autocomplete_bar")
=> 2
Я упускаю что-то очевидное? Источник просто:
# Delete a key.
def del(*keys)
synchronize do
@client.call [:del, *keys]
end
end
мне кажется, что это должно сработать, чтобы передать ему массив …?
Ответ №1:
Небольшое кодирование, посвященное тому, как работает оператор splat:
def foo(*keys)
puts keys.inspect
end
>> foo("hi", "there")
["hi", "there"]
>> foo(["hi", "there"])
[["hi", "there"]]
>> foo(*["hi", "there"])
["hi", "there"]
Таким образом, передача обычного массива приведет к тому, что этот массив будет оцениваться как единый элемент, так что вы получите массив внутри массива в вашем методе. Если вы предваряете массив символом * при вызове метода:
$redis.del(*keys)
Это позволяет методу знать, что его нужно распаковать / не принимать никаких дальнейших аргументов. Таким образом, это должно решить проблему, с которой вы столкнулись!
Просто ради дальнейшего разъяснения, это работает:
>> foo("hello", *["hi", "there"])
Это приводит к синтаксической ошибке:
>> foo("hello", *["hi", "there"], "world")
Комментарии:
1. причины удаления нескольких (тысяч) ключей: SystemStackError: слишком глубокий уровень стека, о котором сообщается в этом выпуске github.com/redis/redis-rb/issues/122 . Это решается прямым вызовом метода на клиенте:
$redis.client.call [:del, *keys]
Ответ №2:
Для приложения Rails, над которым я работаю, мне нужно было протестировать результаты загрузки и выгрузки данных redis.
Пространство имен определяется средой, что позволяет избежать взаимодействия с разработкой. Это сработало хорошо.
def clear_redis_cache
keys = $redis.keys "#{namespace}*"
$redis.del(*keys) unless keys.empty?
end
Комментарии:
1. Monkey-исправление пространства имен redis для этого gist.github.com/mahemoff/c3abf31d5eeda2b2ac751dccd5182cb9
2. -1 потому что команда KEYS не является готовой к работе командой. Это вызовет блокировку соединения и повлияет на другие команды. Подробнее redis.io/topics/latency
Ответ №3:
Этого лучше достичь с помощью перечислителя, возвращаемого scan_each
.
scan_each(match: 'autocomplete_*').each do |key|
del key
end
Это не загружает все соответствующие ключи в память сразу, поэтому он не будет ограничен локальной памятью.
Комментарии:
1. ЭТО , так много всего этого! Я использовал оригинальный метод poster для сканирования всей базы данных на предмет совпадающих ключей, а затем пытался удалить массив, содержащий тысячи ключей. Это заняло больше часа. Этот
scan_each
метод сократил время до 10 минут!