Создание системы уведомлений

Я нахожусь в начале создания системы уведомлений в стиле Facebook для нашей страницы (тип социальной игры), и теперь я изучаю, какой был бы лучший способ для разработки такой системы. Меня не интересует, как нажимать на пользователя уведомления или что-то в этом роде (на данный момент даже). Я изучаю, как создать систему на сервере (как хранить уведомления, где их хранить, как их извлекать и т.д.).

Итак... некоторые требования, которые у нас есть:

  • В пиковые времена у нас около 1k одновременно зарегистрированных пользователей (и еще много гостей, но они не имеют значения здесь, поскольку у них не будет уведомлений), которые будут генерировать много событий
  • будут разные типы уведомлений (пользователь A добавил вас как друга, пользователь B прокомментировал ваш профиль, пользователю C понравилось ваше изображение, пользователь D избил вас по игре X,...)
  • большинство событий будут генерировать 1 уведомление для 1 пользователя (пользователю X понравилось ваше изображение), но будут случаи, когда одно событие будет генерировать множество уведомлений (например, пользователь Y день рождения).
  • уведомления должны быть сгруппированы вместе; если, например, четыре разных пользователя, например, какое-либо изображение, владелец этого изображения должен получить одно уведомление о том, что четырем пользователям понравилось изображение, а не четыре отдельных уведомления (как это делает FB).

ОК, так что я думал, что я должен создать какую-то очередь, где я буду хранить события, когда они произойдут. Тогда у меня была бы фоновая работа (gearman?), Которая будет смотреть на эту очередь и генерировать уведомления на основе этих событий. Затем это задание будет хранить уведомления в базе данных для каждого пользователя (поэтому, если событие затрагивает 10 пользователей, будет 10 отдельных уведомлений). Затем, когда пользователь откроет страницу со списком уведомлений, я прочитал бы все эти уведомления для него (мы считаем, что ограничиваем это до 100 последних уведомлений) и группируем их вместе, а затем, наконец, отображаем их.

Вещи, которые меня беспокоят с помощью этого подхода:

  • как ад:)
  • - это база данных, которая лучше всего хранит здесь (мы используем MySQL), или мне нужно использовать что-то еще (redis тоже кажется хорошим)
  • Что я должен хранить как уведомление? идентификатор пользователя, идентификатор пользователя, который инициировал событие, тип события (чтобы я мог их группировать и отображать соответствующий текст), но затем я не знаю, как хранить фактические данные уведомления (например, URL & title изображение, которое понравилось). Должен ли я просто "выпекать" эту информацию при создании уведомления, или я должен хранить идентификатор записи (изображение, профиль,...), а также извлекать информацию из БД при отображении уведомления.
  • здесь должно быть ОК, даже если мне нужно обрабатывать 100 уведомлений "на лету" при отображении страницы уведомлений
  • возможная проблема с производительностью при каждом запросе, потому что мне нужно будет отображать количество непрочитанных уведомлений для пользователя (что может быть проблемой в своем собственном, так как я собирал группы вместе). Этого можно избежать, хотя если бы я создал вид уведомлений (где они сгруппированы) в фоновом режиме, а не на лету

Итак, что вы думаете о моем предлагаемом решении и моих проблемах? Прошу прокомментировать, если вы думаете, что я должен упомянуть что-нибудь еще, что было бы здесь актуально.

О, мы используем PHP для нашей страницы, но это не должно быть большим фактором здесь, я думаю.

Ответ 1

Уведомление о чем-то (объекте = событие, дружба..) было изменено (глагол = добавлено, запрошено..) кем-то (актером) и сообщено пользователю (теме). Вот нормализованная структура данных (хотя я использовал MongoDB). Вы должны уведомить некоторых пользователей об изменениях. Таким образом, это уведомления для каждого пользователя.. означает, что если было задействовано 100 пользователей, вы генерируете 100 уведомлений.

╔═════════════╗      ╔═══════════════════╗      ╔════════════════════╗
║notification ║      ║notification_object║      ║notification_change ║
╟─────────────╢      ╟───────────────────╢      ╟────────────────────╢
║ID           ║—1:n—→║ID                 ║—1:n—→║ID                  ║
║userID       ║      ║notificationID     ║      ║notificationObjectID║
╚═════════════╝      ║object             ║      ║verb                ║
                     ╚═══════════════════╝      ║actor               ║
                                                ╚════════════════════╝

(Добавьте поля времени, где вы сочтете нужным)

Это в основном для группировки изменений для каждого объекта, чтобы вы могли сказать "У вас есть 3 запроса друзей". И группировка на актера полезна, так что вы можете сказать: "Пользователь Джеймс Бонд внес изменения в вашу кровать". Это также дает возможность переводить и подсчитывать уведомления по своему усмотрению.

Но поскольку объект - это всего лишь идентификатор, вам нужно получить дополнительную информацию об объекте, который вы хотите, с отдельными вызовами, если только объект не изменится, и вы хотите показать эту историю (например, "пользователь изменил название события на..." )

Так как уведомления близки к реальному времени для пользователей на сайте, я бы привязал их к узлу nodejs + websockets client с обновлением php, чтобы обновить nodejs для всех слушателей по мере добавления изменений.

Ответ 2

Это действительно абстрактный вопрос, поэтому я думаю, нам просто придется обсудить это, а не указывать, что вам следует или не следует делать.

Вот что я думаю о ваших проблемах:

  • Да, система уведомлений сложна, но не так. У вас может быть много разных подходов к моделированию и внедрению таких систем, и они могут иметь от среднего до высокого уровня сложности;

  • Песняльно, я всегда стараюсь сделать базу данных управляемой. Зачем? Потому что я могу гарантировать полный контроль над всем, что происходит - но это только я, вы можете контролировать без подхода, основанного на базе данных; поверьте мне, вы захотите контролировать этот случай;

  • Позвольте мне показать вам реальный случай, чтобы вы могли начать где-то. В прошлом году я смоделировал и реализовал систему уведомлений в какой-то социальной сети (конечно, не как facebook). Как я использовал для хранения уведомлений? У меня была таблица notifications, где я сохранил generator_user_id (идентификатор пользователя, который генерирует уведомление), target_user_id (вид очевидного, не так ли?), notification_type_id (что ссылаются на другую таблицу с типами уведомлений), и все необходимое для заполнения нам нужно заполнить нашими таблицами (отметки времени, флаги и т.д.). В моей таблице notification_types использовалось отношение с таблицей notification_templates, в которой хранились определенные шаблоны для каждого типа уведомлений. Например, у меня был тип POST_REPLY, у которого был тип шаблона вроде {USER} HAS REPLIED ONE OF YOUR #POSTS. Оттуда я просто рассматривал {} как переменную и # как ссылку ссылки;

  • Да, производительность должна и должна быть в порядке. Когда вы думаете об уведомлениях, вы думаете о том, что сервер нажимает с головы до ног. Либо если вы собираетесь делать это с помощью ajax-запросов или чего-то еще, вам придется беспокоиться о производительности. Но я думаю, что во второй раз беспокоюсь,

Эта модель, которую я разработал, конечно, не единственная, за которой вы можете следовать, ни лучшая. Надеюсь, мой ответ, по крайней мере, следует за вами в правильном направлении.

Ответ 3

╔════════════════════╗
║notification        ║
╟────────────────────╢
║Username            ║
║Object              ║
║verb                ║
║actor               ║
║isRead              ║
╚════════════════════╝

Это хороший ответ, а не наличие 2 коллекций. Вы можете запрашивать имя пользователя, объект и isRead для получения новых событий (например, 3 ожидающих запроса друга, 4 вопроса и т.д.)

Сообщите мне, есть ли проблема с этой схемой.

Ответ 4

Я лично не очень хорошо понимаю диаграмму для принятого ответа, поэтому я собираюсь привязать базу данных диаграммы базы данных о том, что я мог бы узнать из принятого ответа и других страниц.

enter image description here

Усовершенствования хорошо приняты.