Как вложить список в структуру в Redis, чтобы уменьшить верхний уровень? - PullRequest
1 голос
/ 30 января 2020

Я хочу сохранить некоторые метаданные в redis.

meta_key = build_key()
meta_data = {
    "user": 12345,
    "tag": "D12321341234123",
    }
res = redis_sip.hmset(meta_key, meta_data)

Работает как положено.

Теперь я хочу сохранить список в этой структуре meta_data и иметь возможность добавить элемент в список.

Например:

meta_data = {
    "user": 12345,
    "tag": "D12321341234123",
    "items": []
    }

Но сразу возникает исключение:

redis.exceptions.DataError: Invalid input of type: 'list'. Convert to a byte, string or number first.

Я считаю, что могу создать новый ключ и использовать zadd для ведения списка. Однако я хотел бы минимизировать количество ключей. Это потому, что мне нужно быстро сделать ключи недействительными, как только пользователь выйдет из системы. Приведение ключей к минимуму может помочь мне

1) быстро выселить ключи

2) избежать ошибки, потому что есть меньше ключей, чтобы держать вкладку на

Есть ли В любом случае я могу сохранить список в значении redis и легко расширить список?

Ответы [ 2 ]

1 голос
/ 30 января 2020

В большинстве случаев лучше использовать SADD или ZADD с командами конвейерной обработки. Используйте транзакцию MULTI / EXE C, если существует риск того, что другой клиент может получить ключ между ними, и, следовательно, получить неполный объект.

Строгое список в поле ha sh может быть оправдано в несколько случаев.

Что касается «Быстрого выселения ключей», обязательно используйте UNLINK вместо DEL.

Если вы решите преобразовать в строку, вот как атомарно поддерживать вставку и удалить в JSON -кодированный массив в поле ha sh с использованием Lua и Lua CJSON library :

Вставить :

local items = cjson.decode(redis.call('HGET', KEYS[1], 'items'))
table.insert(items, ARGV[1])
return redis.call('HSET', KEYS[1], 'items', cjson.encode(items))

Удалить по значению :

local items = cjson.decode(redis.call('HGET', KEYS[1], 'items'))
local pos = -1;
for i, v in ipairs(items) do
    if ARGV[1] == v then
        pos = i
        break
    end
end
if pos == -1 then
    return -1
else
    table.remove(items, pos)
    return redis.call('HSET', KEYS[1], 'items', cjson.encode(items))
end

Пример использования :

> HGETALL meta_key
1) "user"
2) "12345"
3) "tag"
4) "D12321341234123"
5) "items"
6) "{}"
> EVAL "local items = cjson.decode(redis.call('HGET', KEYS[1], 'items')) \n table.insert(items, ARGV[1]) \n return redis.call('HSET', KEYS[1], 'items', cjson.encode(items))" 1 meta_key value1
(integer) 0
> HGETALL meta_key
1) "user"
2) "12345"
3) "tag"
4) "D12321341234123"
5) "items"
6) "[\"value1\"]"
> EVAL "local items = cjson.decode(redis.call('HGET', KEYS[1], 'items')) \n table.insert(items, ARGV[1]) \n return redis.call('HSET', KEYS[1], 'items', cjson.encode(items))" 1 meta_key value2
(integer) 0
> HGETALL meta_key
1) "user"
2) "12345"
3) "tag"
4) "D12321341234123"
5) "items"
6) "[\"value1\",\"value2\"]"
> EVAL "local items = cjson.decode(redis.call('HGET', KEYS[1], 'items')) \n local pos = -1; \n for i, v in ipairs(items) do \n     if ARGV[1] == v then \n     pos = i \n     break \n end \n end \n if pos == -1 then \n     return -1 \n else \n     table.remove(items, pos) \n return redis.call('HSET', KEYS[1], 'items', cjson.encode(items)) \n end" 1 meta_key value1
(integer) 0
> HGETALL meta_key
1) "user"
2) "12345"
3) "tag"
4) "D12321341234123"
5) "items"
6) "[\"value2\"]"
> EVAL "local items = cjson.decode(redis.call('HGET', KEYS[1], 'items')) \n local pos = -1; \n for i, v in ipairs(items) do \n     if ARGV[1] == v then \n     pos = i \n     break \n end \n end \n if pos == -1 then \n     return -1 \n else \n     table.remove(items, pos) \n return redis.call('HSET', KEYS[1], 'items', cjson.encode(items)) \n end" 1 meta_key value3
(integer) -1
> HGETALL meta_key
1) "user"
2) "12345"
3) "tag"
4) "D12321341234123"
5) "items"
6) "[\"value2\"]"
1 голос
/ 30 января 2020

Я считаю, что могу создать новый ключ и использовать zadd для ведения списка

да, я бы так и сделал.

однако, если вы хотите минимизировать ключ, у вас нет другого пути, кроме как преобразовать объект в текст и использовать set; также проанализируйте строку, как только вы ее вернете.

это ограничит вам доступ к одному свойству объекта, но вы, вероятно, уже знаете это.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...