Как ограничить список лидеров в 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