Я нахожусь в начале создания системы уведомлений в стиле Facebook для нашей страницы (типа социальных игр), и сейчас я изучаю, как лучше всего разработать такую систему. Меня не интересует, как отправлять уведомления пользователю или что-то в этом роде (на данный момент даже). Я изучаю, как построить систему на сервере (как хранить уведомления, где хранить их, как получать их и т.д. ...).
Итак ... некоторые требования, которые у нас есть:
- в пиковое время у нас есть около 1k одновременно зарегистрированных пользователей (и еще много гостей, но здесь они не имеют значения, так как у них не будет уведомлений), которые будут генерировать много событий
- будут различные типы уведомлений (пользователь A добавил вас в друзья, пользователь B прокомментировал ваш профиль, пользователю C понравилось ваше изображение, пользователь D избил вас в игре X, ...)
- большинство событий генерируют 1 уведомление для 1 пользователя (пользователю X понравилось ваше изображение), но будут случаи, когда одно событие будет генерировать много уведомлений (например, это день рождения пользователя Y)
- уведомления должны быть сгруппированы вместе; если, например, четыре разных пользователя любят какое-то изображение, владелец этого изображения должен получить одно уведомление о том, что изображение понравилось четырем пользователям, а не четырем отдельным уведомлениям (как FB)
Итак, я подумал, что мне нужно создать какую-то очередь, где я буду хранить события, когда они происходят. Тогда у меня будет фоновая работа ( gearman ?), Которая будет просматривать эту очередь и генерировать уведомления на основе этих событий. Затем это задание будет хранить уведомления в базе данных для каждого пользователя (поэтому, если событие затрагивает 10 пользователей, будет 10 отдельных уведомлений). Затем, когда пользователь открывал страницу со списком уведомлений, я читал все эти уведомления для него (мы надеемся ограничить это до 100 последних уведомлений) и группировал их вместе, а затем, наконец, отображал их.
Что меня беспокоит в этом подходе:
- сложный как черт :)
- Является ли база данных лучшим хранилищем здесь (мы используем MySQL) или я должен использовать что-то еще (redis тоже кажется подходящим)
- что я должен хранить как уведомление? идентификатор пользователя, идентификатор пользователя, который инициировал событие, тип события (чтобы я мог сгруппировать их и отобразить соответствующий текст), но тогда я вроде не знаю, как хранить фактические данные уведомления (например, URL-адрес и заголовок изображения, которое было понравилось). Должен ли я просто «испечь» эту информацию при создании уведомления или сохранить идентификатор затрагиваемой записи (изображение, профиль, ...) и извлечь информацию из БД при отображении уведомления.
- производительность должна быть в порядке, даже если мне нужно обрабатывать 100 уведомлений на лету при отображении страницы уведомлений
- возможная проблема с производительностью при каждом запросе, потому что мне пришлось бы отображать количество непрочитанных уведомлений для пользователя (что само по себе может быть проблемой, поскольку я собирал уведомления вместе). Этого можно избежать, если бы я генерировал представление уведомлений (где они сгруппированы) в фоновом режиме, а не на лету
Так что вы думаете о моем предложенном решении и моих проблемах? Пожалуйста, прокомментируйте, если вы считаете, что я должен упомянуть что-либо еще, что будет иметь отношение к делу.
О, мы используем PHP для нашей страницы, но это не должно быть большим фактором здесь, я думаю.
источник
Ответы:
Уведомление о том, что кто-то (субъект) что-то (объект = событие, дружба ..) был изменен (глагол = добавлен, запрошен ..) и передан пользователю (субъекту). Вот нормализованная структура данных (хотя я использовал MongoDB). Вам необходимо уведомить определенных пользователей об изменениях. Таким образом, это уведомления для каждого пользователя. Это означает, что если в нем участвует 100 пользователей, вы генерируете 100 уведомлений.
(Добавьте поля времени, где вы считаете нужным)
Это в основном для группировки изменений по объектам, чтобы вы могли сказать «У вас есть 3 запроса на добавление в друзья». А группировка по актерам полезна, чтобы вы могли сказать: «Пользователь Джеймс Бонд внес изменения в вашей постели». Это также дает возможность переводить и считать уведомления, как вам нравится.
Но, поскольку объект - это просто идентификатор, вам нужно было бы получать всю дополнительную информацию об объекте, который вы хотите, с помощью отдельных вызовов, если только объект на самом деле не изменяется, и вы хотите показать эту историю (например, «пользователь изменил название события на ...» «)
Поскольку уведомления для пользователей на сайте близки к реальному времени, я бы связал их с клиентом nodejs + websockets с php, отправляющим обновление для nodejs для всех слушателей по мере добавления изменений.
источник
is_notification_read
вnotification
таблице, и пометить его соответствующим образом, если оно естьunread
,read
илиdeleted
.Это действительно абстрактный вопрос, поэтому я думаю, что нам просто нужно обсудить его, а не указывать, что вы должны или не должны делать.
Вот что я думаю о ваших проблемах:
Да, система уведомлений сложна, но все же не так чертовски. У вас может быть много разных подходов к моделированию и реализации таких систем, и они могут иметь от среднего до высокого уровня сложности;
Pesonally, я всегда стараюсь делать вещи на основе базы данных. Зачем? Потому что я могу гарантировать полный контроль над всем, что происходит - но это только я, вы можете иметь контроль без подхода, управляемого базой данных; поверь мне, ты захочешь контролировать дело;
Позвольте мне привести пример из реальной ситуации для вас, чтобы вы могли начать с чего-то. В прошлом году я смоделировал и внедрил систему уведомлений в какой-то социальной сети (конечно, не в 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-запросами или чем-то еще, вам придется беспокоиться о производительности. Но я думаю, что это второй раз;
Эта модель, которую я разработал, конечно, не единственная, которой вы можете следовать, и не самая лучшая. Я надеюсь, что мой ответ, по крайней мере, следует за вами в правильном направлении.
источник
Это выглядит хорошим ответом, а не иметь 2 коллекции. Вы можете запросить по имени пользователя, объекту и isRead, чтобы получить новые события (например, 3 ожидающих запроса на добавление в друзья, 4 задаваемых вопроса и т. Д.)
Дайте мне знать, если есть проблемы с этой схемой.
источник
Лично я не очень хорошо понимаю диаграмму для принятого ответа, поэтому я собираюсь приложить базу диаграмм базы данных, на которой я мог бы извлечь уроки из принятого ответа и других страниц.
Улучшения хорошо приняты.
источник