#python #redis
#python #redis
Вопрос:
Я использую Redis в качестве хранилища данных / кэша для своего приложения. Я отправляю данные в экземпляр Redis после преобразования их в строку. Мои данные представляют собой объект класса Python (то есть пары ключ-значение, но преобразованные в строку). Я использую библиотеку Redis на Python.
Мои данные периодически передаются, и возможно, что данные с определенного хоста могут перестать передаваться из-за сбоя хоста и т.д. Я хочу иметь возможность удалять данные с этого хоста, как только хост выйдет из строя. У меня есть триггер, который уведомляет мое приложение о выходе из строя хоста и т.д.
Однако я не уверен в том, как эффективно удалить данные из Redis, отключив обработку данных и проверив наличие определенной пары ключ-значение в данных. Я хотел бы сделать это на месте, если это возможно. Любая помощь с этим будет по-настоящему оценена!
Редактировать:
Это то, что я использую для отправки данных в redis:
self.redis.zadd("mymsgs", pickle.dumps(msg), int(time.time() 360))
Само сообщение не соответствует формату:
{'hostname': 'abc1', 'version': 'foo', 'uptime': 'bar'}
Комментарии:
1. Разве вы не можете каким-то образом добавить имя хоста в ключ Redis? Таким образом, вы могли бы использовать такие вещи, как
hostname-foo*
? Или, может быть, вы могли бы изучить, поможет ли таймер для автоматического удаления ключа через некоторое время? (Я имею в виду redis.io/commands/expire ) ?2. @BorrajaX Итак, вот в чем дело. Данные, которые я храню в Redis, представляют собой измененную версию dict, которая содержит имя хоста и его значение в виде kvp. Я новичок в Redis как таковом. Нет ли другого способа удаления из хранилища данных?
3. Когда вы говорите
kvp
… Это ключ Redis? Потому что, AFAIK, вы можете использовать подстановочные знаки только в ключах, а не в значениях. Как выглядит ваш ключ? Можете ли вы отредактировать вопрос, чтобы привести пример?4. Пожалуйста, смотрите мою правку выше.
kvp
здесь не упоминается ключ Redis. Насколько я понимаю,mymsgs
в моем случае это был бы ключ Redis? Пожалуйста, поправьте меня, если я ошибаюсь…. Кроме того, внутри ключа есть ли способ удалить данные на основе соответствия шаблону строки?
Ответ №1:
Если я правильно понял, я бы рекомендовал (если это возможно, конечно) немного изменить формат ключей. Вместо использования универсального mymsgs
в качестве ключа я бы рекомендовал каким-то образом добавить имя хоста к самому ключу. Например, это может быть mysgs_from_HOSTNAME
.
Поскольку вы можете использовать подстановочные знаки для извлечения ключей, когда вы хотите получить все сообщения, вы могли бы просто перечислить совпадающие ключи mysgs_from_*
, а затем получить значения этих ключей. Таким образом, когда вы знаете, что вызываемое имя хоста HOSTNAME
недоступно, вы могли бы быстро очистить все его записи, выполнив delete("mysgs_from_HOSTNAME"
)`
Смотрите этот пример:
import redis
import time
import pickle
redis_connection = redis.Redis(host='localhost', port=6379, db=0)
# This "for" loop is just a simple populator, to put a bunch of key/values in Redis
for hostname in ['abc1', 'foo2', 'foo3']:
msg = {'hostname': hostname, 'version': 'foo', 'uptime': 'bar'}
# Step 1, store the data using a key that contains the hostname:
redis_key = "messages_from_host_%s" % hostname
redis_connection.zadd(redis_key, pickle.dumps(msg), int(time.time() 360))
# Ok... I have some sample data in Redis now...
# Shall we begin?...
# Let's say I wanna get all the messages from all the hosts:
# First, I find all the keys that can contain messages from hosts
matching_keys = redis_connection.keys("messages_from_host_*")
print "Got these keys that match what I wanna get: %s" % matching_keys
# Then I iterate through the keys and get the actual zrange (~value) of each
print "These are the messages from all those hosts:"
for matching_key in matching_keys:
messages = [pickle.loads(s) for s in redis_connection.zrange(matching_key, 0, -1)]
print messages
# Let's say that now, I discover that host called `foo2` is down, and I want
# to remove all its information:
redis_connection.delete("messages_from_host_foo2")
# All the entries referred to the host `foo2` should be gone:
print "Now, I shouldn't bee seing information from `foo2`"
matching_keys = redis_connection.keys("messages_from_host_*")
for matching_key in matching_keys:
messages = [pickle.loads(s) for s in redis_connection.zrange(matching_key, 0, -1)]
print messages
Который выводит:
Got these keys that match what I wanna get: ['messages_from_host_foo2', 'messages_from_host_foo3', 'messages_from_host_abc1']
These are the messages from all those hosts:
[{'uptime': 'bar', 'hostname': 'foo2', 'version': 'foo'}]
[{'uptime': 'bar', 'hostname': 'foo3', 'version': 'foo'}]
[{'uptime': 'bar', 'hostname': 'abc1', 'version': 'foo'}]
Now, I shouldn't bee seing information from `foo2`
[{'uptime': 'bar', 'hostname': 'foo3', 'version': 'foo'}]
[{'uptime': 'bar', 'hostname': 'abc1', 'version': 'foo'}]
Комментарии:
1. Спасибо! Попробую сделать это и отмечу вопрос как ответ, если смогу заставить его работать 🙂
2. Я надеюсь, что это поможет 🙂