Удаление объектов из redis на основе соответствия шаблону

#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. Я надеюсь, что это поможет 🙂