Все привет.
Намечается один проект в котором будет лента аля ВК, фейсбук и тд.
Стал я думать и понял, что не могу придумать архитектуру БД при которой это будет работать при куче пользователей...
Реляционные БД - это куча записей в таблице и джойны(или доп запросы) для лайков и комментов и самого контента на который ссылается запись.
MongoDB и тд - это необходимость обновлять ленту каждого пользователя для которого доступна моя запись при любом действии. А как быть когда у чела 100500 подписчиков, например. Я мало знаю о монго, но читал пару статей в которых описывали как же это плохо как раз в таких случаях.
В общем, попытки найти ответы на мои вопросы порождают у меня еще больше вопросов
Может кто-нибудь делать уже подобное? Поделитесь советом, плз)
Проект будет на Yii2.
Лента новостей. Как же сделать правильно?
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Лента новостей. Как же сделать правильно?
Задачка занятная. Как-то её Бородин рассказывал на конференциях: http://spb-borodin.livejournal.com/. В одном из постов у него есть намёки.
Нравится Yii? Давайте сделаем его лучше!.
Re: Лента новостей. Как же сделать правильно?
Sam Dark, спасибо большое. Познавательно. Появились мысли как устроить всё.
Re: Лента новостей. Как же сделать правильно?
У меня схожая диллема пока не решена. Например, товары в е-магазине
1 - товар
2 - EAV (entity–attribute–value)
3 - оценки (не просто звёзды, а достоинства, недостатки и комментарий)
4 - обсуждения (или комментарии)
5 - подписка по email на изменение свойств (например, скидка)
или простые статьи с оценками, комментариями и подписчиками - суть та-же
Каждая такая сущность ("доп" свойство) хранится в своей таблице БД.
Просто выводить такой список, еще ладно - любые допы можно "наджойнить".
А вот как это всё фильтровать по разным доп.параметрам: EAV, оценкам, подпискам и т.п.
И, конечно, это всё без 100500 запросов к БД и мега-массивов в памяти, на рендер одной страницы.
Впорос про архитектуру решения: подскажите, куда думать?
1 - товар
2 - EAV (entity–attribute–value)
3 - оценки (не просто звёзды, а достоинства, недостатки и комментарий)
4 - обсуждения (или комментарии)
5 - подписка по email на изменение свойств (например, скидка)
или простые статьи с оценками, комментариями и подписчиками - суть та-же
Каждая такая сущность ("доп" свойство) хранится в своей таблице БД.
Просто выводить такой список, еще ладно - любые допы можно "наджойнить".
А вот как это всё фильтровать по разным доп.параметрам: EAV, оценкам, подпискам и т.п.
И, конечно, это всё без 100500 запросов к БД и мега-массивов в памяти, на рендер одной страницы.
Впорос про архитектуру решения: подскажите, куда думать?
- samdark
- Администратор
- Сообщения: 9489
- Зарегистрирован: 2009.04.02, 13:46
- Откуда: Воронеж
- Контактная информация:
Re: Лента новостей. Как же сделать правильно?
EAV в реляционной базе — это уже плохо для производительности. По определению.
Нравится Yii? Давайте сделаем его лучше!.
Re: Лента новостей. Как же сделать правильно?
Много читал сегодня, голова уже не соображает, но пришел к следующему:
Вся лента хранится в одной таблице/коллекции - с конкретным видом хранилища еще не определился.
Что-то типа:
id|user_id|model_name|model_id|comments_count|likes_count|created_at
Ну и может еще какие-то поля будут. Комменты и лайки пересчитывать планирую при непосредственном добавлении/удалении. Контент остается в модели.
Еще у документо-ориентированной есть определенные плюсы. Например, хранение всех user_id которые лайкали запись прямо в документе. Атомарные операции очень удобно использовать. Но если предположить, что будет очень много лайков(200к например) то при чтении такого документа будет отожрана куча памяти. Правда и тут есть решение, можно лайки вынести в отдельную коллекцию и читать их только если нужно будет отображать тех кто лайкнул. Так же возможно комментарии войдут в документ, хотя не уверен, так как не понял как потом пейджер делать или подгрузку.
В MySQL мне бы пришлось делать отдельную таблицу, наверное, для лайков. Получается, что при 1кк записей в таблице ленты и по 100 лайков в среднем на запись, мы получаем просто какое-то заоблачное кол-во записей в таблице лайков.
Другого решения ведь нет для MySql?
Пугают еще и отзывы о MongoDB по поводу надежности. Не хотелось бы безвозвратно потерять инфу по всем лайкам и комментариям.
Так же пока не понял как быть с ограничение в 16мб на документ. Так как массив из 200к user_id отжирает 30мб+ памяти, то есть документ должен весить столько же?
1кк записей и 200к лайков для одной записи очень оптимистично, конечно, но хочется сразу сделать правильно так как проект очень даже интересный и, скорее всего, жить будет
Кто что думает?
ps. Сильно не пинайте, опыта работы с большими БД нет, о NoSQL только читал пока.
Вся лента хранится в одной таблице/коллекции - с конкретным видом хранилища еще не определился.
Что-то типа:
id|user_id|model_name|model_id|comments_count|likes_count|created_at
Ну и может еще какие-то поля будут. Комменты и лайки пересчитывать планирую при непосредственном добавлении/удалении. Контент остается в модели.
Еще у документо-ориентированной есть определенные плюсы. Например, хранение всех user_id которые лайкали запись прямо в документе. Атомарные операции очень удобно использовать. Но если предположить, что будет очень много лайков(200к например) то при чтении такого документа будет отожрана куча памяти. Правда и тут есть решение, можно лайки вынести в отдельную коллекцию и читать их только если нужно будет отображать тех кто лайкнул. Так же возможно комментарии войдут в документ, хотя не уверен, так как не понял как потом пейджер делать или подгрузку.
В MySQL мне бы пришлось делать отдельную таблицу, наверное, для лайков. Получается, что при 1кк записей в таблице ленты и по 100 лайков в среднем на запись, мы получаем просто какое-то заоблачное кол-во записей в таблице лайков.
Другого решения ведь нет для MySql?
Пугают еще и отзывы о MongoDB по поводу надежности. Не хотелось бы безвозвратно потерять инфу по всем лайкам и комментариям.
Так же пока не понял как быть с ограничение в 16мб на документ. Так как массив из 200к user_id отжирает 30мб+ памяти, то есть документ должен весить столько же?
1кк записей и 200к лайков для одной записи очень оптимистично, конечно, но хочется сразу сделать правильно так как проект очень даже интересный и, скорее всего, жить будет
Кто что думает?
ps. Сильно не пинайте, опыта работы с большими БД нет, о NoSQL только читал пока.
Re: Лента новостей. Как же сделать правильно?
Сегодня задумался на тем как выбирать из ленты записи тех людей, на которых я подписан и, признаться, тупик...
Если на примере мускула то получается вложенный запрос в условии? WHERE user_id IN (SELECT user_id FROM subscribers WHERE subscriber_id = :my_id) ? Будет ли такое работать вообще если в обеих таблицах миллионы записей?
На Монго получается не намного лучше, надо взять массив всех людей на кого я подписан и передать в IN. Но тут я вообще пока не понимаю как он переварит допустим 100к+ айди в запросе...
Гуру СУБД отзовитесь плз)
Если на примере мускула то получается вложенный запрос в условии? WHERE user_id IN (SELECT user_id FROM subscribers WHERE subscriber_id = :my_id) ? Будет ли такое работать вообще если в обеих таблицах миллионы записей?
На Монго получается не намного лучше, надо взять массив всех людей на кого я подписан и передать в IN. Но тут я вообще пока не понимаю как он переварит допустим 100к+ айди в запросе...
Гуру СУБД отзовитесь плз)
- slavcodev
- Сообщения: 3134
- Зарегистрирован: 2009.04.02, 21:42
- Откуда: Valencia
- Контактная информация:
Re: Лента новостей. Как же сделать правильно?
Информация для размышлений по "ленты новостей" (для еще большей боли в голове)
1) Возможно пригодится систему обмена сообщениями (СОС), например RabbitMQ, можно свою команду простую написать, для крона.
2) Процесс работы:
- При регистрации пользователя Х, создается очередь сообщений Х
- Другие пользователи подписываются на эту очередь (Follow User, Friendship)
- Когда пользователь Х добавляет новость, в очередь сообщений Х попадает сообщение "Пользователь Х добавил новость У", далее другой процесс (СОС) рассылает это сообщение всем подписавшимся
- Для новой новости создается очередь У, на которую подписываются, например все кто добавит коммент, и в эту очередь попадают сообщения для рассылки, когда комменты добавляются
- Если пользователь Х удаляет новость, в очередь Х отправляется соотв. сообщение и СОС удаляет у подписавшися эту запись
1) Возможно пригодится систему обмена сообщениями (СОС), например RabbitMQ, можно свою команду простую написать, для крона.
2) Процесс работы:
- При регистрации пользователя Х, создается очередь сообщений Х
- Другие пользователи подписываются на эту очередь (Follow User, Friendship)
- Когда пользователь Х добавляет новость, в очередь сообщений Х попадает сообщение "Пользователь Х добавил новость У", далее другой процесс (СОС) рассылает это сообщение всем подписавшимся
- Для новой новости создается очередь У, на которую подписываются, например все кто добавит коммент, и в эту очередь попадают сообщения для рассылки, когда комменты добавляются
- Если пользователь Х удаляет новость, в очередь Х отправляется соотв. сообщение и СОС удаляет у подписавшися эту запись
Жду Yii 3!