Redis: есть ли способ добавить в отсортированный набор, только если набор существует?

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

из-за того, что это делается с pipeline, поэтому требуется много затрат, чтобы проверить, существует ли отсортированный набор, каждый раз из Redis.


person Abdutahir    schedule 01.07.2016    source источник
comment
Привет, Поскольку вы делаете это с конвейером, я предлагаю сгруппировать это по ключу и выполнить проверку один раз для каждого ключа, чтобы вам не приходилось проверять все добавления.   -  person Malinga    schedule 01.07.2016
comment
Спасибо за ваш комментарий @Malinga. Я делаю так: сначала проверяю существование каждого ключа с конвейером, затем сопоставляю результат с ключами, наконец, zadd с конвейером в соответствии с результатом.   -  person Abdutahir    schedule 01.07.2016
comment
Хорошо, могу я узнать среднее количество полей в одном отсортированном наборе и количество отсортированных наборов   -  person Malinga    schedule 01.07.2016
comment
В каждом отсортированном наборе сотни элементов и сотни тысяч отсортированных наборов. @Малинга   -  person Abdutahir    schedule 04.07.2016
comment
это означает, что когда вы получаете 100 заддов, вам может потребоваться выполнить проверку существования только несколько раз, поскольку они могут относиться только к нескольким отсортированным наборам?   -  person Malinga    schedule 04.07.2016


Ответы (2)


Вы можете запускать сценарии Lua в конвейере — следующий добавит все аргументы к предоставленному ключу, при условии, что ключ существует:

local exists = redis.call('EXISTS', KEYS[1])
if exists == 1 then
  redis.call('ZADD', KEYS[1], unpack(ARGV))
end

Примечание: здесь нет проверки ошибок (т. е. тип ключа — zset, аргументы допустимы...), чтобы сэкономить циклы ЦП и упростить пример. Также нет кода возврата - добавьте его, если он вам нужен.

person Itamar Haber    schedule 01.07.2016
comment
Этот код всегда будет запускать команду ZADD (оба 0 и 1 оцениваются как true в Lua при преобразовании в логическое значение). Правильный способ сделать это if redis.call('EXISTS', KEYS[1]) == 1 then .... - person kYuZz; 06.09.2016

Вы можете использовать команду exists (возвращает 1, если ключ присутствует, иначе 0), чтобы проверить, присутствует ли отсортированный набор или нет, и если существует zset, то в обратном вызове команды exists вы можете вызвать zadd для добавления в zset.

Также exists является операцией O(1). Вы можете прочитать об этом на странице http://redis.io/commands/exists.

пример кода

var r = redis.createClient(6379,"127.0.0.1");
r.exists(zsetKey, function(err, isExists){ 
  if(isExists){ // isExists = 1 if zsetKey exists
    r.zadd(zetKey, score, member, function(insertErr, insertReply){
      // add to zset
    })
  }else{
    //key not present
  }
})
person raghav    schedule 01.07.2016
comment
Спасибо за ответ. Но из-за работы с pipeline я не могу проверять существование каждый раз перед zadd. - person Abdutahir; 01.07.2016
comment
Этот код работает медленно, потому что требует двух циклов обмена данными с сервером. Но что еще хуже, это не безопасно для условий гонки: другой клиент может удалить отсортированный набор в любое время между вызовами exists() и zadd(). Это особенно неприятный тип состояния гонки, потому что он маловероятен, пока ваш код не находится под высокой нагрузкой. - person kYuZz; 07.09.2016