Комментарии 29
А почему бы не отдавать RSS каждому юзеру а в приложении подписывать уже на сами rss потоки?
Если вы храните id новости в ленте но за контентом, как я понял, ходите каждый раз в другой сервис, зачем нужен механизм с удалением новости из всех лент? Вырежте контент перед выдачей, в момент запроса данных пользователем, когда будете контент собирать по ID. А потом тихонько пометьте записи к удалению в бэкграунде.
Я конечно не знаю всей внутренней кухни, но, исходя из ваших цифр по объемам, возможно, достаточно было сделать таблицу news_id, tag_id, published_at. (денормализация новостей по тегам ..без денормализации по юзерам).
Она по объему равнялась бы news_tags (что в тысячи раз меньше полной денормализации).
Это гораздо проще в обслуживании
При полной денормализации у вас получился бы объем где то от 500млн. записей. Поэтому вам приходится усложнять систему за счёт "активных" пользователей, построения на лету и прочего. При денормализации без юзеров объем таблицы всегда равен объему таблицы news_tags (в принципе её можно даже убрать). При этом такая таблица/покрывающий индекс скорее всего полностью в оперативную память поместится.
P.S. когда вы пишите, что пользователь может быть подписан на сотни тегов, то... согласно вашим данным в среднем пользователь подписан на 16/5 чуть более 3х тегов. ..пусть будет 10 :)
Справедливо, но судя по тому что в статье сказано, тут рассказ упрощённый. И подписки у них могут быть не только на теги, но и на конкретных редакторов и на что-то там ещё. Это уже более сложный менеджмент и больше строк. Может поэтому другим путём пошли
Тоже не понимаю, зачем так усложнять себе жизнь дополнительным базами, когда достаточно таблицы с идентификаторами, наполняемыми триггерами
В статье это объяснил – с NoSQL удобнее обновлять и очищать данные. Для таблиц придётся делать ровно ту же логику, хранить и поддерживать бизнес-логику в коде удобнее, чем в триггерах.
я это не понял, что значит удобнее?
сейчас нужно буквально держать отдельные базы данных, дублирующие информацию, поддерживать этот код, синхронизировать и получать проблемы рассинхронизации.
если все что будет добавлено в базу - это кеш-ссылки, это буквально мизер, данные и так уже есть, запросы потребуют минимум правки (убрать части, собирающие данные, так как они уже будут собраны тригерами) и вся проблема - чутчуть замедленное добавление данных
p.s. если вам нравится работать с готовыми сеарилизованными данными, тригерами добавляйте не списки id в М-к-М а json-чиками, нужно тестировать что будет быстрее и на сколько добавит это тормозов при добавлении тех же подписок (ведь придется обновлять весь json вместо добавления 1 записи), но сейчас еще хуже, ведь в соседнюю базу вообще кусок всего переезжает
В книжке кабанчика высоко нагруженные системы писали про вашу задачу, про условный твиттер.
Если коротко то речь такая:
Если у автора мало подписчиков - мы платим за него при публикации. Если у автора огромное количество подписчиков мы платим за него при чтении.
То есть один запрос в монгу для непопулярных авторов, один запрос в вашу бд для популярных авторов. В конце мержите данные.
Решал такую же задачу, не стал ничего выдумывать и взял твитеровскую архитектуру - хранение в Redis, максимально быстро. Мастер данные в постгри, сервис ленты берет обновление из кафки.
Кмк, решение уйти от sql - бесполезное.
Вы вот указываете формат хранения в монгоДб, а список тегов лежит внутри сложного объекта. Теперь надо перебрать все ленты в монгодб, в них перебрать все теги в поисках того, который есть в текущей новости. Ок, добавляем на это поле индекс. Судя по описанию - монгоДб делает примерно то же, что и обычная СУБД: выносит это в отдельную таблицу и делает там двоичное дерево со ссылками на исходные записи. Что существенно изменилось то? Таблица индекса, критичная для производительности - примерно та же с теми же принципами.
Ну а перенос расчета на запись с чтения вполне логичен. Тут меньше операций и меньше требований к скорости (ваш редактор 5 секунд без проблем подождет, а вот пользователь с каждой лентой так не будет).
В Монго удобнее работа с вложенными объектами, можно за один запрос найти все объекты с определенной новостью. В статье подробнее рассказал о преимуществах.
Чисто технически можно решить задачу и на sql и хранить также готовые ленты в реляционных таблицах
можно за один запрос найти все объекты с определенной новостью
я все равно не понимаю, что ж такого она делает нового?
в чем проблема в sql найти все объекты с определенной новостью? что join/union придется писать на каждый тип объекта? ну так и в монго вы скорее всего подобным будете заниматься - у вас же в ленте лишь id (т.е. ссылки, а сами объекты лежат в отдельных "документах) - все равно придется за ними сходить и это либо аналог join/union (что исполнится на стороне движка СУБД), либо что еще хуже - переход контекста выполнения в код и вызов вторым запросом оттуда.
Я подозреваю, что будет “переход контекста выполнения в код и вызов вторым запросом оттуда” - т.е. эта частичка стала работать хуже, чем было до этого.
Например, в Монго есть удобные операторы для поиска внутри объекта или для обновления части данных внутри json.
SQL плохо работает с json полями, там по сути надо всё поле обновлять.
Ну что же, друзьям я на эту ленту уже жаловался, теперь и авторам могу пожаловаться. Специально открыл ещё раз её (стараюсь туда не заходить, это паноптикум какой-то)
Прошу прощения, что не по технической части, но техническую часть имеет смысл обсуждать когда результат соответствует цели, а мне кажется, что это совсем не так.
Перехожу в "Мою ленту"
Вижу, что у меня ровно три любимые темы: Спартак, Валерий Карпин, Алессандро Дель Пьеро. Вроде понятно, что я хочу видеть. Разве это не логично, что, если я подписан на теги "Спартак" и "Алессандро Дель Пьеро", то я должен где-то иметь возможность увидеть все статьи, новости, посты (можно и без них) по этим тегам, желательно в хронологическом порядке, может с какими-то фильтрами?
Мои ожидания, мои проблемы, я знаю. Что я вижу в итоге?
Скрытый текст
Новость: «Бешикташ» готов фиксированно заплатить 5 млн евро за Кисляка. Остальная часть предложения в 30 млн – в бонусах (Иван Карпов)
Статья: В битву Рыбакиной и Соболенко за №1 рейтинга влезли еще две участницы. Вот все сценарии
Пост: " СУМАСШЕДШИЙ ФАКТ: Килиан Мбаппе забил 86 голов за «Реал Мадрид» к началу своего третьего сезона в клубе."
Новость: Экс-чемпион мира по снукеру Грэм Дотт признан виновным в сексуальном насилии над детьми
Пост «Барселона» только что подписала все документы по сделке с Домиником Ливаковичем; подтверждаю — here we go now.
Статья "Ударом разорвал сопернику яичко, дрался за стиралки, выступал до 50. Великий Роберто Дюра "
Пост "Доминик Ливакович пройдёт медосмотр в качестве нового игрока «Барселоны» завтра. "
Новость "«Бешикташ» через посредника заявил о готовности заплатить до 30 млн евро за Кисляка. ЦСКА исключил продажу хавбека (Иван Карпов) "
Это видимо Рекомендательная лента.
2 статьи и одну новость я уже увидел сегодня на главной, только кроме них я увидел ещё кучу всего, что сюда может и попало, но не будет увидено мной, т.к. количество мусора значительно больше: Посты идут каким-то валом (чуть ниже в ленте их уже по 4 подряд), местами и ещё и на одну тему (Ливакович). Две новости про Кисляка (ну то есть из интересов моих ML решил что мне интересно ЦСКА? серьёзно?). +Возможно веса подкручены в модельке в сторону постов.
Взаимодействие с постами отличается от остального. Открываются на всплывашке, а не переход по ссылке. Надо видимо угадывать ещё, где посты (а он может быть на весь экран), а где статьи по наличию комментариев и реакций. Так себе дизайн, мне кажется.
Ну и по классике, обновление страницы и ты больше не увидишь эту ленту, увидишь другую. Конечно же полный расколбас по хронологии. Для рилсов это может норм, а вот новости про концерт Канье Веста имхо должны идти в хронологическом порядке (наконец-то музыкальные новости на нашем музыкальном сайте).
Переключаюсь на подписки (это же та самая персональная лента наконец-то?). В подписках видно только авторов и блоги на которых подписаны, статьи там не увидишь. При этом, если ты подписан на блог, то в ленте на статье указан только автор и ты просто не понимаешь, почему у тебя Дуанель и Михаил Морозов видны, хотя ты на них не подписан. А оказывается они авторы блогов, на которые ты пописан, но это в ленте не видно.
Кроме того в ленте снова плывет хронология
Скрытый текст

По моим впечатлениям, скорость может и приличная, только вот результат выдачи вообще далек от сколько-нибудь правильного. И что ещё хуже, он совсем не тот, который ты ожидаешь.
Это мне очень напоминает мою волну от яндекс музыки. Где за два года мне не попалось ни одной песни 3 групп. отмеченных мной как любимые. Всего у меня отмечено любимыми было 5 групп.
Или как новости Москвы от мейл ру, где именно новостей Москвы - одна штука, остальное геополитика или про загнивающий запад.
Так что может это и вправду я такой неправильный со своими ожиданиями.
наконец научился печатать 100500 символов в минуту, но такая фигня получается
каждый высоконагруженный сервис пиарится на сайте в т.ч. как они круто собирают ленту подписок/рекомендаций, и само собой каждый из этих сервисов делает эту ленту максимально неудобно для пользователя.
Наверное это тренд современности (в отличии от 10-15 лет назад) - делать максимально плохо и неудобно для пользователя.
Да, вы правы, это рекомендательная лента. Текущий алгоритм работает не идеально, о проблемах коллеги знают и прям сейчас ими занимаются.
вы уверены что это 'проблемы'? случайно такое поведение не сделать, это явно намеренное поведение.
Да и про персональную я ниже расписал. +Вы пишите
Именно о персональной ленте дальше и пойдёт речь
До этого момента мы рассматривали только новости. Но со временем персональная лента стала включать и пользовательский контент.
Добавляем посты
Помимо новостей появились блоги и посты. Пользователь может подписываться:
на теги (те же самые, что и в новостях)
Т.е. утверждается, что в персональной ленте есть новости и подписка по ним по тегам. Но по факту в персональной ленте только блоги и посты. А где новости?
Персональная лента с новостями есть в приложении, на сайте фильтр только по постам. Возможно в будущем и на сайте добавится.
Блин, ну классно, в начале статьи скриншот с сайта, теперь оказывается надо смотреть в приложение. Чем дальше, тем хуже прям всё.
Теперь выясняется, что Моя лента на сайте и в приложении это разные вещи, ещё одна причина ими не пользоваться. В приложении вообще не ясно где пост, где статья, где новость. Различить можно только зайдя внутрь. Новости снабжаются какими-то рандомными фотками которых нигде больше нет и подобраны просто из архива видимо по действуюшему лицу в новости, в итоге занимают пол экрана.Зачем??
Реально, я очень люблю ваш сайт, пользуюсь наверно где-то с 2000-2001, поэтому и бомбит так.
При таком объёме данных
На таких объёмах можно все в оперативной памяти хранить и собирать в реальном времени. Редис с ZSET или эластик с обратным индексом - думаю будет в пределах микросекунд.
не обязательно стороннее хранилище городить, ведь можно буквально все поместить в ram backend приложения (дублирование с базой данных), все кроме собственно данных (тексты) можно полностью уместить в оперативную память вместе с индексами (заточенными на работу с оперативкой), работать будет не хуже любых нагромождений из микросервисов и уж точно дешевле (для превышения сотен гигабайт потребуются иные объемы, на несколько порядков больше).

Почему мы перестали собирать персональную ленту SQL‑запросами