Создание системы уведомлений
Я нахожусь в начале создания системы уведомлений в стиле 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]()
Усовершенствования хорошо приняты.