Сводка : Для примерно 1 миллиона активных пользователей и 150 миллионов хранимых действий я упрощаю:
- Использование реляционной базы данных для хранения уникальных действий (1 запись на действие / «вещь, которая произошла»). Сделайте записи максимально компактными. Структура, позволяющая быстро получить пакет действий по идентификатору операции или с помощью набора идентификаторов друзей с временными ограничениями.
- Публикуйте идентификаторы активности в Redis при каждом создании записи активности, добавляя идентификатор в список «потока активности» для каждого пользователя, который является другом / подписчиком, который должен видеть действие.
Запрос Redis, чтобы получить поток активности для любого пользователя, а затем получить необходимые данные из БД по мере необходимости. Вернитесь к запросам по БД по времени, если пользователю нужно просматривать далеко назад (если вы даже предлагаете это)
Я использую простую старую таблицу MySQL для обработки около 15 миллионов операций.
Это выглядит примерно так:
id
user_id (int)
activity_type (tinyint)
source_id (int)
parent_id (int)
parent_type (tinyint)
time (datetime but a smaller type like int would be better)
activity_type
сообщает мне тип активности, source_id
сообщает мне запись, с которой связано действие. Так что, если тип действия означает «добавленный избранный», то я знаю, что source_id ссылается на идентификатор избранной записи.
parent_id
/ parent_type
полезны для моего приложения - они говорят мне, с чем связано действие. Если бы книга была добавлена в избранное, то parent_id / parent_type сказал бы мне, что действие относится к книге (типу) с заданным первичным ключом (id)
Я индексирую на (user_id, time)
и запрашиваю действия, которые user_id IN (...friends...) AND time > some-cutoff-point
. Отключение идентификатора и выбор другого кластерного индекса может быть хорошей идеей - я не экспериментировал с этим.
Довольно простой материал, но он работает, он прост, и с ним легко работать, когда ваши потребности меняются. Кроме того, если вы не используете MySQL, возможно, вы сможете улучшить индексирование.
Для более быстрого доступа к самым последним действиям я экспериментировал с Redis . Redis хранит все свои данные в памяти, поэтому вы не можете поместить туда все свои действия, но вы можете хранить достаточно для большинства популярных экранов на вашем сайте. Последние 100 для каждого пользователя или что-то в этом роде. С Redis в миксе, это может работать так:
- Создайте свою запись активности MySQL
- Для каждого друга пользователя, создавшего действие, вставьте идентификатор в свой список действий в Redis.
- Обрезать каждый список до последних X элементов
Redis работает быстро и предлагает способ передачи команд по одному соединению, поэтому отправка активности для 1000 друзей занимает миллисекунды.
Для более подробного объяснения того, о чем я говорю, см. Пример Redis в Twitter: http://redis.io/topics/twitter-clone
Обновление за февраль 2011 У меня сейчас 50 миллионов активных действий, и я ничего не изменил. Хорошая вещь о том, чтобы сделать что-то подобное этому, состоит в том, что это использует компактные, маленькие ряды. Я планирую внести некоторые изменения, которые повлекут за собой гораздо больше действий и больше запросов об этих действиях, и я определенно буду использовать Redis для ускорения работы. Я использую Redis в других областях, и он действительно хорошо работает для некоторых видов проблем.
Обновление за июль 2014 года Ежемесячно мы получаем около 700 000 активных пользователей. Последние пару лет я использую Redis (как описано в маркированном списке) для хранения последних 1000 идентификаторов активности для каждого пользователя. Обычно в системе около 100 миллионов записей активности, и они все еще хранятся в MySQL и имеют ту же структуру. Эти записи позволяют нам избегать меньшего объема памяти Redis, они служат для записи данных об активности, и мы используем их, если пользователям необходимо найти страницы назад во времени, чтобы что-то найти.
Это не было умным или особенно интересным решением, но оно хорошо мне помогло.