Как ограничить список лидеров в Redis только N элементами?

Мне нужно создать таблицу лидеров с максимальным количеством элементов, скажем N? Я знаю, как использовать LPUSH + LTRIM, чтобы ограничить размер списка до N элементов. Как реализовать это для списка лидеров, используя отсортированный набор Redis

Пока что мой подход состоит в том, чтобы сделать это в 3 этапа: а) ЗАДД, чтобы добавить счет + пункт в таблицу лидеров

б) найти ранг N-го элемента (я не уверен, как это сделать)

c) сделать таблицу лидеров ZREMRANGEBYRANK 0 rank_of_the_nth_element.

Есть ли способ лучше?

2 ответа

Решение

У меня на самом деле есть рабочее приложение, которое использует Redis. Вы можете проверить это здесь. В моем приложении таблицы лидеров ограничены сверху n баллы, а также старые баллы сбрасываются, когда они становятся слишком старыми (поэтому могут быть дневные, недельные, месячные, годовые табло с высокими оценками)

В любом случае, я думаю, что вы рассчитываете на общее лидерство, поэтому низкие баллы отталкиваются. В смысле Redis Sorted Set, если вы настроили так, чтобы высокие баллы оставались (они внизу), а низкие баллы должны уходить (они вверху), тогда вы бы сделали что-то вроде:

ZREMRANGBYRANK leaderboard 0 -100

В этом примере предполагается, что вы хотите сохранить последние 100 баллов.

Может быть, вы инвертируете баллы, так что "высокий балл" 1000 сохраняется как -1000 в redis, поэтому он является первым в отсортированном наборе. В этом случае это будет так же, как указано выше, но используйте ZREMRANGEBYRANK leaderboard 100 -1 удалить все элементы после первых 100.

Обновление: понял, что есть ZREMRANGEBYRANK так упростил мой пример.

Ваше предлагаемое решение должно также работать. Если вы хотите найти оценку nth элемент, вы можете использовать это:

hundredth_entry = ZRANGE leaderboard 100 100
hundredth_score = ZSCORE leaderboard hundredth_entry
ZREMRANGEBYSCORE leaderboard -inf (hundredth_score

( Это сделано для того, чтобы диапазон НЕ включался, поэтому будет удалено все МЕНЬШЕ, чем сотая оценка, но не сама сотая оценка.

Лучшая реализация алгоритма OP:

redis.call("ZADD", KEYS[1], ARGV[1]+0, ARGV[2])
local n = redis.call("ZCARD", KEYS[1])
if n > ARGV[3]+0 then 
    redis.call("ZREMRANGEBYRANK", KEYS[1], 0, n-ARGV[3]-1) 
end

Затем заменить

ZADD key score member

с

EVAL script 1 key score member cap
Другие вопросы по тегам