Бэкэнд-архитектура горячих страниц в стиле Reddit

Я пытаюсь создать внутренний дизайн того, как Reddit вычисляет и обслуживает горячие страницы. Я также использую «горячий» рейтинг для заказа постов на моем сайте. У меня есть некоторые проблемы с этим, которые я пытаюсь преодолеть. Вот некоторые из способов, которые, по моему мнению, могут иметь смысл для проектирования:

Вычисление горячих значений: в данный момент я вычисляю значение и сохраняю его в базе данных вместе с самим голосованием каждый раз, когда кто-то голосует за сообщение или каждый раз, когда кто-то загружает сообщение. Это, наверное, не здорово. Я думаю о том, чтобы просто обновлять горячее значение всех сообщений через задание cron, например, каждые 5 минут и только для сообщений, которые старше 2 месяцев, например. Этот дизайн должен работать для тысяч и тысяч сообщений, некоторые я не уверен, что это лучшее решение, но я читал, что Reddit, по крайней мере, в начале, использовал задания cron для этого.

Запросы сообщений. Это то, о чем я больше всего беспокоюсь в данный момент. Прямо сейчас проблема заключается в том, что если я прокручиваю (больше сообщений загружается внизу страницы), я могу видеть дубликаты сообщений из-за того, что сообщения поднимаются и опускаются в горячем значении. Прямо сейчас каждый раз, когда загружаются новые сообщения, выполняется запрос к базе данных для получения сообщений. Я думаю, что будет иметь смысл использовать memcached и кэшировать запросы для сообщений (это нужно будет применить ко многим страницам), но я не уверен, что это полностью решит мою проблему. В идеале я нахожу решение, которое в основном «снимает» (кэширует?) БД и загружает из этой версии таблицы в БД до тех пор, пока не будет загружена новая страница.

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


person arian1123    schedule 08.01.2016    source источник


Ответы (2)


Вы не должны так сильно беспокоиться о дублирующих сообщениях. У большинства сайтов (включая Reddit) есть эта проблема.

Я не думаю, что есть решение, которое хорошо масштабируется. Большинство сайтов ценят производительность и масштабируемость, а не согласованность. Вот почему nosql становится все более популярным для подобных вещей. Они не гарантируют согласованность (или только возможную согласованность), но взамен обеспечивают более высокую производительность и горизонтальную масштабируемость.

Если вы действительно хотите решить эту проблему, я бы посмотрел на стороне клиента. Из вашего описания я понимаю, что у вас будет сайт с бесконечной прокруткой. Вы можете позволить клиенту «запомнить», какие посты уже показаны. Если сервер отправляет ему больше сообщений (при прокрутке вниз), клиент может отфильтровать те, которые он уже показывает выше, например. сохраняя список идентификаторов сообщений.

person Bartez    schedule 08.01.2016
comment
На самом деле я уже сохраняю сообщение, которое пользователь видел, как переменную сеанса, и это работает достаточно хорошо, просто то, как это работает, может быть ошибочным в некоторых случаях, особенно на мобильных устройствах, когда по какой-либо причине переменная иногда очищается где-то в середина. Возможно, работать с этим и настраивать его — лучший способ. Также есть мысли о вычислении горячих значений? Было бы лучше сделать это в cronjob и, возможно, сохранить эти значения в memcached? - person arian1123; 09.01.2016
comment
Для вычисления горячих значений я бы выбрал подход cron, тем более что время, вероятно, является важным аспектом расчета «горячих». Он также является наиболее последовательным и простым в настройке. Если расчет влияет на производительность, вы можете, например. временно просто понизьте частоту вычислений. - person Bartez; 09.01.2016
comment
Когда вы сохраняете показанные сообщения как переменную сеанса, это все еще на стороне сервера. Я имел в виду, что клиент должен решить, какие сообщения добавлять. Это может, например. посмотрите в его DOM, чтобы проверить, какие сообщения уже показаны. Я не совсем уверен, что делать, если пользователь прокручивает страницу очень далеко или занимает много времени, так что большинство ответов с сервера уже будут показаны. В этом случае все ответы с сервера уже могут быть показаны, а текущие самые горячие уже не возвращаются. Возможно, в такой ситуации клиент снова начнет запрашивать самые горячие посты? - person Bartez; 09.01.2016
comment
О, я вижу, что ты говоришь. Я тоже думал о чем-то подобном. Мне просто было трудно думать о том, как это реализовать. Любые идеи? - person arian1123; 09.01.2016

Прямо сейчас проблема заключается в том, что если я прокручиваю (больше сообщений загружается внизу страницы), я могу видеть дубликаты сообщений из-за того, что сообщения поднимаются и опускаются в горячем значении.

Это давняя проблема в Reddit. Простого решения нет, но вы можете использовать подходы на стороне клиента, чтобы скрыть сообщения, которые уже присутствуют на текущей странице.

Вычисление горячих значений: на данный момент я вычисляю значение и сохраняю его в базе данных вместе с самим голосованием каждый раз, когда кто-то голосует за сообщение или каждый раз, когда кто-то загружает сообщение. Это, наверное, не здорово.

горячий выбор Reddit не учитывает количество просмотров, поэтому нет необходимости обновлять их при каждом просмотре потока. Однако они обновляют значения сортировки при каждом голосовании: вверх, вниз или без голосования. Пока вы делаете это в отдельной очереди и у вас достаточно обработчиков очереди, это достаточно масштабируемый подход.

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

person Xiong Chiamiov    schedule 18.02.2016