Есть приложение, которое использует mysql для хранения информации про пользователей и nosql/redis для обеспечения быстрой записи/чтения информации.
Этих процедур (чтения/запись) проходит очень много, по этому выбран редис.
часть задачи полностью портируется на redis. но есть вопрос на который не могу пока найти решение.
Приложение должно показывать количество людей «онлайн».
Если на sql можно при запросе обновлять поле online текущим timestamp и потом сделать where online>timestamp-15m и все покажет
то как быть в key-value хранилище пока не могу никак понять.
был вариант создавать ключ, который менялся бы раз в 15 минут. Например:
online_20110602_13_0
online_20110602_13_1
online_20110602_13_2
online_20110602_13_3
online_20110602_14_0
online_20110602_14_1
…
и писать туда +1 если запрос был в эти 15 минут.
Но такой вариант не приемлем, так как при переходе с 14 на 15 минуту счетчик будет показывать 0.
В общем вопрос такой. Как вывести и сохранять «онлайн» людей.
(ПС: Есть вариант писать текущие секунды, а потом в цикле по убыванию считывать последние 900 (15минут) и считать их, но это мне кажется через задницу решение)
Собственно вопрос решил след образом:
При хите формируется ключ online_20110602_13_1, куда пишется юзерИД, ключ создается на 15минут.
Каждую минуту — новый ключ.
Когда нужно получить список — проходит последние 15 ключей и объединяет. Получается, что некоторые значения дублируются, но не критично.
По скольку ключ делается на 15М, то они чистятся и в редиске всегда максимум 15 ключей на кол-во онлайнов.
Ок, вариант получше :) хранить айдишники юзеров в поминутных ключах online_20110602_13_00, ..., online_20110602_13_59, устанавливая каждому TTL 15 минут, добывать с помощью sunion из последних 15 ключей. Если точность не особо важна, то можно не поминутно, а попятиминутно хранить.
По вашему варианту — если ж писать +1 по каждому запросу, то будет не кол-во онлайн пользователей, а хитов. Выходит, чтобы не было дубликатов по-любому нужно хранить ID пользователей.
Я задачу решал так: записываю в редис (sadd) айдишник и ставлю/пролонгирую «отложенную» задачу (memcacheq) удалить его (srem) через 15 минут.
Можно так:
при хите — ZADD guys_online <unix_timestamp> <user_id>
получить число онлайн ребят — ZCOUNT guys_online <unix_timestamp-15*60> +inf
время от времени чистить старые записи
— ZREMRANGEBYSCORE guys_online -inf (<unix_timestamp-15*60>