Задать вопрос

Как организовать хранение данных для новостной ленты социальной сети?

Как организовать хранение данных для новостной ленты?
База данных Cockroach DB (ядро от PostgreSQL ). Основные сущности: пользователи, связь пользователей (друзья, подписчики), объекты (товары), сферы, подписки пользователей на сферы, посты, подборки.
Как я понял, есть два основных подхода:
1. Формировать ленту на лету из РСУБД. Реализацию такого подхода в данном случае не представляю возможным, потому что такой запрос должен будет затрагивать десятки таблиц с десятками join-ов, а итоговый набор записей будет содержать совершенно разнородные данные, для чего РСУБД не совсем подходит.
2. Готовить ленту для каждого пользователя отдельно. То есть возникает в какой-либо сфере событие, его нужно записать в ленту для миллиона подписчиков. Этот метод считаю более подходящим, но смущает два обстоятельства: нагрузка на запись в БД и объемы данных для хранения, хаос в разрешении всевозможных ситуаций: подписок, отписок, удалении постов и так далее.
Какую базу данных выбрать для реализации подхода 2 или ему подобных? Casandra и HBase или Aerospike, Scylla?
  • Вопрос задан
  • 443 просмотра
Подписаться 3 Средний 9 комментариев
Решения вопроса 2
hint000
@hint000
у админа три руки
2. Готовить ленту для каждого пользователя отдельно. То есть возникает в какой-либо сфере событие, его нужно записать в ленту для миллиона подписчиков.
Беда этого варианта в том, что из миллиона подписчиков половина не заходили в ленту полгода+, ещё 200 тысяч не заходили месяц+, ещё 200 тысяч не заходили неделю+, а ваша БД всё это время бесполезно молотит для всего миллиона.

Здесь нет простого решения (в соцсетях вообще много непростого). Вам нужно как минимум комбинировать первый и второй метод (а может быть ещё и какой-то третий и какой-то четвёртый). И чтобы делать это оптимально (не требуя на миллион подписчиков столько же мощностей, сколько Вконтактик потратил бы на 10 миллионов подписчиков), потребуются действительно умные алгоритмы, а не только совет насчёт подходящей СУБД. Навскидку, для событий от друзей больше подходит второй метод, а для событий сфер - первый метод. Но это не точно. Можно применять второй метод только для тех, кто заходил не больше суток назад и т.п.
Ответ написан
Комментировать
@Arlekcangp
Разработчик, Лид, Архитектор ПО
Как уже указал hint000 первый вариант можно использовать только очень ограниченно. Для второго лучше взять что-нибудь документо-ориентированное или мульти-колоночное, что позволит денормализовать структуру данных. Т е вам нужно хранить некое представление "обобщённой ленты" (возможно отдельно для каждой сферы, что бы потом это можно было шардировать) и там будут лежать эвенты в каждом из которых может быть записано много разной информации. Возможно какие то данные пользователей, для формирования их персональной ленты в момент запроса. В принципе и на базе postgres можно организовать такую таблицу, c большим количеством полей, плюс postgres умеет класть в колонки json, что может помочь. Но в любом случае лучше применить паттерн CQRS и исходные данные хранить нормализованными, а при их изменении бросать эвент, который пойдёт в RabbitMQ или Kafka и будет обрабатываться пулом инстансов, обновляющих записи в лентах. А раз так, то там вообще можно взять что-нибудь типа elastic search. На чтение она должна быть очень быстрой.
хаос в разрешении всевозможных ситуаций: подписок, отписок, удалении постов и так далее.

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

Войдите, чтобы написать ответ

Похожие вопросы