Комментарии 8
А почему бы не отдавать RSS каждому юзеру а в приложении подписывать уже на сами rss потоки?
Если вы храните id новости в ленте но за контентом, как я понял, ходите каждый раз в другой сервис, зачем нужен механизм с удалением новости из всех лент? Вырежте контент перед выдачей, в момент запроса данных пользователем, когда будете контент собирать по ID. А потом тихонько пометьте записи к удалению в бэкграунде.
Я конечно не знаю всей внутренней кухни, но, исходя из ваших цифр по объемам, возможно, достаточно было сделать таблицу news_id, tag_id, published_at. (денормализация новостей по тегам ..без денормализации по юзерам).
Она по объему равнялась бы news_tags (что в тысячи раз меньше полной денормализации).
Это гораздо проще в обслуживании
При полной денормализации у вас получился бы объем где то от 500млн. записей. Поэтому вам приходится усложнять систему за счёт "активных" пользователей, построения на лету и прочего. При денормализации без юзеров объем таблицы всегда равен объему таблицы news_tags (в принципе её можно даже убрать). При этом такая таблица/покрывающий индекс скорее всего полностью в оперативную память поместится.
P.S. когда вы пишите, что пользователь может быть подписан на сотни тегов, то... согласно вашим данным в среднем пользователь подписан на 16/5 чуть более 3х тегов. ..пусть будет 10 :)
В книжке кабанчика высоко нагруженные системы писали про вашу задачу, про условный твиттер.
Если коротко то речь такая:
Если у автора мало подписчиков - мы платим за него при публикации. Если у автора огромное количество подписчиков мы платим за него при чтении.
То есть один запрос в монгу для непопулярных авторов, один запрос в вашу бд для популярных авторов. В конце мержите данные.
Решал такую же задачу, не стал ничего выдумывать и взял твитеровскую архитектуру - хранение в Redis, максимально быстро. Мастер данные в постгри, сервис ленты берет обновление из кафки.

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