Как организовать хранение данных для новостной ленты социальной сети?
2. Готовить ленту для каждого пользователя отдельно. То есть возникает в какой-либо сфере событие, его нужно записать в ленту для миллиона подписчиков.Беда этого варианта в том, что из миллиона подписчиков половина не заходили в ленту полгода+, ещё 200 тысяч не заходили месяц+, ещё 200 тысяч не заходили неделю+, а ваша БД всё это время бесполезно молотит для всего миллиона.

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