Создание персонализированной новостной ленты в стиле Facebook: SQL, MongoDB? - PullRequest
3 голосов
/ 13 декабря 2011

Я создаю новостную ленту в стиле Facebook.Это означает, что он создается из множества таблиц SQL, и каждый тип данных имеет определенную структуру.Но это становится очень тяжелым для загрузки, и я надеялся сделать его еще более сложным ...

Вот что я делаю сейчас:

Модель пользователя:

  def updates(more_options = {})
        (games_around({},more_options) + friends_statuses({},more_options).sort! { |a,b| b.updated_at <=> a.updated_at }.slice(0,35) + friends_stats({:limit  => 10},more_options) + friends_badges({:limit  => 3},more_options)).sort! { |a,b| b.updated_at <=> a.updated_at }
  end

Пример данных Badges:

  def friends_badges(options = {:limit  => 3}, more_options = {})
    rewards = []
      rewards = Reward.find(:all, options.merge!(:conditions  => ["rewards.user_id IN (?)",self.players_around({},more_options).collect{|p| p.id}], :joins  => [:user, :badge], :order  => "rewards.created_at DESC"))            
    rewards.flatten
  end

Просмотр новостной ленты:

<% for update in @current_user.updates %>
        <% if update.class.name == "Status" %>
            <% @status = update %>
            <%= render :partial  => "users/statuses/status_line", :locals  => {:status  => update} %>
        <% elsif update.class.name == "Game" %>
            <%= render :partial => "games/game_newsfeed_line", :locals  => {:game  => update} %>
        <% elsif update.class.name == "Stat" %>
            <%= render :partial => "stats/stat_newsfeed_line", :locals  => {:stat  => update} %>
        <% elsif update.class.name == "Reward" %>
            <%= render :partial => "badges/badge_newsfeed_line", :locals  => {:reward  => update} %>
        <% end %>
    <% end %>

ОпцииЯ думал о:

  • Создание таблицы «Feed» и предварительная обработка большинства обновлений для каждого пользователя с фоновым заданием.Скорее всего почасовой крон.Я бы сохранял весь HTML-код для каждого обновления.
  • Сохраняйте исходную структуру, но работайте над кэшированием каждого обновления отдельно (сейчас у меня нет кэширования)
  • Переключитесь на MongoDB, чтобы получить более быстрый доступк базе данных

Скажу сразу, я не эксперт, Rails сделал первые шаги легкими, но теперь, когда загружено более 150 запросов SQL на страницу, я чувствую, что это неконтролируемо и требуетэкспертная точка зрения ...

Что бы вы сделали?

Спасибо за вашу драгоценную помощь,

Screenshots

1 Ответ

2 голосов
/ 13 декабря 2011

Ваш код мало что мне говорит;Я думаю, было бы полезно, если бы вы могли выложить свою структуру данных в виде простого JSON / SQL.

В любом случае, я бы сериализовал поток каждого пользователя в MongoDB.Я бы не стал хранить HTML в базе данных по разным причинам (по крайней мере, на этом уровне программного обеспечения);вместо этого вы должны сохранить соответствующие данные в (возможно, полиморфной) коллекции.Извлечение новостной ленты очень просто, индексация проста и т. Д. Структура представления по существу не изменится.Если позже вы захотите изменить HTML, это тоже легко.

Недостатком является то, что это будет дублировать много данных.Если у людей может быть много последователей, это может стать проблемой.Может помочь использование массивов идентификаторов пользователей вместо одного идентификатора пользователя (если информация одинакова для всех подписчиков), но она также ограничена.

Для очень больших проблем с ассоциацией существует только кэширование.Насколько я понимаю, магия и в фейсбуке, и в твиттере заключается в том, что они не очень часто попадают в БД и хранят много данных в оперативной памяти.Если вы связываете миллиарды элементов, это становится проблемой даже в оперативной памяти.

Обновления должны записываться непрерывно, а не ежечасно.Предположим, у вас много трафика, а почасовое обновление занимает 30 минут.Теперь наихудший случай - 90 минут.задержка.Если вы обрабатываете изменения вовремя, вы можете сократить это до 5 минут.

В какой-то момент вам придется добавить предположения, использовать кэширование и некоторую эвристику.Некоторые примеры:

  • Чем более свежий твит, тем больше трафика он увидит.У него больше шансов на ретвит, и это видно гораздо чаще.Храните его в оперативной памяти.
  • Ваша страница обзора временной шкалы facebook 1991 года, вероятно, не будет меняться ежедневно, поэтому это кандидат на долгосрочное кэширование вывода.
  • Текущая активность на Facebook, вероятно, подвергнется большому количеству записей.Кэширование вывода здесь не сильно поможет.Опять же, объект должен храниться в оперативной памяти.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...