Вконтакте: как сделан раздел "Мои новости"?

Wicked

Новичок
Вконтакте: как сделан раздел "Мои новости"?

В качестве разминки для мозга... обсудим, как оно может быть сделано?

Что видно снаружи:
1) новости хранятся 10 дней
2) при загрузке подсасываются ajax'ом с таким содержанием:
Код:
{
      "rows": "html с новостями",
      "pages": "
        <ul class=\"pageList\">
          <li class=\"current\">1</li>
          <li><a href=\"newsfeed.php?section=&offset=50\" onclick=\"return getPage(50)\">2</a></li>
          <li><a href=\"newsfeed.php?section=&offset=100\" onclick=\"return getPage(100)\">3</a></li>
          <li><a href=\"newsfeed.php?section=&offset=650\" onclick=\"return getPage(650)\">»</a></li>
        </ul>",
      "summary": "Показаны последние 50 новостей.",
      "selected_filter": 0,
      "offset": 0,
      "privacy": "0"
}
3) есть пэйджинг с аналогом SQL_CALC_FOUND_ROWS: ссылка » (последняя страница) меняет свой offset в зависимости от новостей, подгруженных последним аякс-запросом
4) можно выбрать список единичных друзей или групп друзей, новости которых будут показаны
5) при показе новостей учитывается фильтр, какие типы новостей показывать ("Фотографии", "Видеозаписи", ...)
6) каждый пользователь может настроить, какие типы своих новостей он хочет "публиковать" друзьям
7) насколько грамотно учитывается доступ - хз. Например, мне пока неясно, показываются ли в новостях фотки, добавленные в приватные альбомы, друзьям, которым доступ к альбому запрещен.
8) когда добавляешь нового друга, его прошлые новости тоже будут отображаться
9) внутри суток однотипные новости одного пользователя объединяются в одну ("Вася пупкин добавил 2 друзей: ...", "Вася Пупкин был отмечен на 2 фотографиях в альбомах: а, б")
10) когда открыта страница, раз в 10 секунд делается пинг с указанием "timestamp=1270199790", на который возвращается delta и апдейтится dom:
{"rows":"html","timestamp":1270199799,"insert":1}
11) статистика: у меня почти 400 друзей, за 10 дней набирается чуть больше 1000 новостей ("все друзья", "все новости")... это где-то 100 в сутки, в часы-пик наверное до 10..15 в час
12) по предварительной оценке (если проигнорировать ботов и принять моих друзей за репрезентативную выборку) - нужно хранить суммарно всего около 200 млн записей
13) про интенсивность обращений, к сожалению, ничего сказать не могу

Интересны всякие варианы реализации, key/value vs mysql vs mysql+key/value, с шардингом и без - все на ваше усмотрение.
 

zerkms

TDD infected
Команда форума
у нас в одном из проектов было организовано следующим образом (правда сама фичка больше похожа на стену в facebook, нежели новости вконтакте)

Код:
CREATE TABLE helpbank.hb_feeds(
  id INT (11) NOT NULL AUTO_INCREMENT,
  user_id BIGINT (20) NOT NULL,
  target_id BIGINT (20) NOT NULL,
  type ENUM (...) NOT NULL,
  object_id INT (11) NOT NULL,
  added TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updated TIMESTAMP DEFAULT '0000-00-00 00:00:00',
  PRIMARY KEY (id),
  UNIQUE INDEX object_type USING BTREE (object_id, type),
...
)
ENGINE = INNODB
из таблицы были убраны незначащие поля, индексы и констрейты.

чтобы её "подогнать" под "новости вконтакте" нужно работать следующим образом:

при добавлении в альбом "фотографии" - добавляем запись с type = photo, object_id = PK фотки

при выборке - делаем тупо по 1 запросу на каждый ряд. т.е.: если у нас есть type:photo+object_id:666 - то делаем из таблицы photos выборку фотографии с id = 666. и так на каждый ряд в списке новостей (у этого варианта есть запас для улучшения - например, на каждый тип сущности отправлять один запрос, собирая PK в кучу через IN()) результаты - в мемкэш, всё тёплое и частоюзаемое остаётся там.

группировка этой схемой не предусмотрена.

в качестве оптимизации можно ложить в эту же базу отрендеренные сущности, прям html, если не боитесь, что в будущем будет сменён дизайн :)

фильтры реализуются тоже просто: тип есть. Сама лента выбирается по `user_id` IN (идшники моих друзей)
 

Wicked

Новичок
моя версия:
есть мемкэш с ключами типа "news_{user_id}", где в значениях хранятся уже отсортированные ленты новостей каждого пользователя в виде: тип,id,тип,id,тип,id,...

делаем:
1) получаем список всех интересующих друзей
2) делаем мультигет ("news_1", "news_2", ...)
3) в пхп вычищаем лишнее по типам записей, убиваем пустые ленты
4) суммируем кол-во записей всего (в худшем случае для моего пользователя - 1000 новостей)
5) делаем выборочный мерж-сорт по id/ts с учетом номера страницы, получая 50 id
6) из мемкэша же получаем детальные описания этих 50 событий
7) выдаем ответ
 
Сверху