Использование Redis для "трендов сейчас"
Я работаю над сайтом с очень высокой пропускной способностью, на котором много элементов, и я пытаюсь реализовать функциональность типа "сейчас в тренде", которая позволила бы пользователям быстро получить список приоритетов из первых N элементов, которые недавно были просмотрены многими людьми, что постепенно исчезают, поскольку они получают меньше просмотров.
Одна из идей о том, как это сделать, состоит в том, чтобы придать больший вес последним просмотрам элемента, например, вес 16 для каждого просмотра элемента за последние 15 минут, вес 8 для каждого просмотра элемента в прошлом 1 час, вес 4 для вещей за прошлые 4 часа, и т. д., но я не знаю, является ли это правильным способом приблизиться к этому.
Я хотел бы сделать это в Redis, в прошлом у нас был хороший успех с Redis для других проектов.
Каков наилучший способ сделать это, как с технической точки зрения, так и с точки зрения определения тенденций?
Первый ответ намекает на решение, но я ищу более подробную информацию - начало щедрости.
Это обе приличные идеи, но недостаточно подробные. Один получил половину награды, но оставив вопрос открытым.
4 ответа
Итак, я бы начал с базового упорядочения по времени (например, zset item_id, оцененного по метке времени), а затем перебрал все на основе взаимодействий. Таким образом, вы можете решить, что одно взаимодействие стоит 10 минут "свежести", поэтому каждое взаимодействие добавляет столько времени к оценке соответствующего элемента. Если все взаимодействия оцениваются одинаково, вы можете сделать это с одним zset и просто увеличивать оценки по мере возникновения взаимодействий.
Если вы хотите иметь какое-то откат, скажем, выигрыш по квадратному корню из счетчика взаимодействий вместо счетчика взаимодействий напрямую, вы можете создать второй zset со своим счетом для взаимодействий и использовать zunionstore, чтобы объединить это с вашим индекс отметки времени. Для этого вы, вероятно, захотите вытащить существующий счет, сделать некоторую математику и поставить новый счет поверх него (zadd позволит вам перезаписать счет)
Zunionstore является потенциально дорогим, и для достаточно больших наборов даже Zadd/ Zincrby становится дорогим. Для этого вам может потребоваться сохранить только N элементов с наибольшим количеством баллов, например, N=10000, в зависимости от потребностей вашего приложения.
Эти две ссылки очень полезны:
http://stdout.heyzap.com/2013/04/08/surfacing-interesting-content/
Алгоритм ранжирования Reddit отлично справляется с тем, что вы описываете. Хорошая запись здесь, которая рассказывает, как это работает.
https://medium.com/hacking-and-gonzo/how-reddit-ranking-algorithms-work-ef111e33d0d9
Рассмотрим упорядоченный набор с количеством просмотров в качестве баллов. всякий раз, когда к элементу обращаются, увеличивают его счет ( http://redis.io/commands/zincrby). таким образом, вы можете получить лучшие предметы из набора, упорядоченного по счетам.
Вам также нужно будет "затухать" элементы, возможно, с помощью внешнего процесса, который уменьшит оценки.