Подтвердить что ты не робот

Если данные постоянно меняются, что вы кешируете? (используя Twitter в качестве примера)

Я потратил некоторое время на изучение кеширования (в основном, redis и memcached), и мне сложно определить, где именно использовать кеширование, когда ваши данные постоянно меняются.

Возьмите Твиттер (просто прочитайте сделайте Twitter на 10000% быстрее). Как вы (или сделаете это) кешируете свои данные, когда большой процент их записей в базе данных постоянно меняется?

Скажите, что у Twitter есть следующие модели: User, Tweet, Follow, Favorite.

Кто-то может опубликовать твит, который получает переиздание один раз в день, а другой, который переиздается тысячу раз в день. Для этого 1000x retweet, так как там около 24 * 60 == 1440 минут в день, это означает, что Tweet обновляется почти каждую минуту (скажем, что у него тоже 440 фаворитов). Тот же, кто следит за кем-то, Чарли Шин даже привлек 1 миллион подписчиков Twitter за 1 день. В этих случаях это не похоже на кеширование, но, возможно, только потому, что я еще не достиг этого уровня.

Скажите также, что средний Twitter-последователь либо чириканье, либо следует/избранное не реже одного раза в день. Это означает, что в наивном случае схемы интро-рельсов таблица пользователей обновляется не реже одного раза в день (tweet_count и т.д.). Этот случай имеет смысл для кэширования профиля пользователя.

Но для примеров 1000x Tweets и 1M, приведенных выше, рекомендуются ли методы кэширования данных?

В частности (предполагая memcached или redis и используя исключительно JSON API (без кэширования страницы/фрагмента)):

  • Вы кэшируете отдельные твиты/записи?
  • Или вы кэшируете фрагменты записей с помощью разбивки на страницы (например, списки переадресации 20)?
  • Или вы кэшируете как записи отдельно, так и на страницах (просмотр одного твита или канала JSON)?
  • Или вы кэшируете списки твитов для каждого другого сценария: твиты домашней хроники, пользовательские твиты, любимые твиты пользователя и т.д.? Или все вышеперечисленное?
  • Или вы разбиваете данные на "самые изменчивые (самые новые)" на "последние несколько дней" на "старые" куски, где "старые" данные кэшируются с более длительной датой истечения срока действия или в отдельные разбитые на страницы списки или что-то еще? И самые новые записи просто не кэшируются вообще. (т.е. если данные зависят от времени как твиты, вы относитесь к нему по-другому, если вы знаете, что старые записи не сильно меняются?)

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

Каковы рекомендуемые стратегии кэширования данных, которые так сильно меняются?

4b9b3361

Ответ 1

Не сказать, что Twitter делает это так (хотя я уверен, что это связано), но: Недавно я познакомился с CQRS + Event Sourcing. (http://martinfowler.com/bliki/CQRS.html + http://martinfowler.com/eaaDev/EventSourcing.html).

В основном: чтение и запись полностью разделены как на приложение, так и на уровне персистентности (CQRS), и каждая запись в систему обрабатывается как событие, на которое можно подписаться (получение событий). Там ему больше (например, возможность воспроизвести весь поток событий, который невероятно полезен для реализации новых функций позже), но это важная часть.

После этого общая практика заключается в том, что a Read Model (mem-mem-cache) воссоздается всякий раз, когда ответственный Projector (то есть: он проектирует событие для новой модели чтения) получает новое событие тип события, на который он подписан.

В этом случае событие может быть TweetHandled, которое будет обрабатываться всеми подписчиками, среди которых RecentTweetsPerUserProjector, TimelinePerUserProjector и т.д., чтобы обновить их соответствующие ReadModels.

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

Я согласен с тем, что в конечном итоге Read Model для Charlie Sheen будет обновляться много (хотя это обновление может быть очень эффективным), поэтому преимущество кеша, вероятно, довольно низкое. Однако, глядя на средние проводки за единицу времени для обычного пользователя, и картина совершенно другая.

Некоторые влиятельные люди в сценарии DDD/CQRS/event-sourcing: Грег Янг, Уди Дахан.

Концепции довольно "глубокие", поэтому не ожидайте, что полностью забудете это через час (по крайней мере, я этого не сделал). Возможно, это недавнее мышление о связанных понятиях полезно: http://www.mindmeister.com/de/181195534/cqrs-ddd-links

Да, я довольно энтузиаст по этому поводу, если вы уже не заметили:)

Ответ 2

Мои скромные 2 цента: Redis позволяет вам управлять своими структурами данных, что означает, что вы можете выполнять операции с оперативной памятью быстрее, чем касаться реляционной базы данных каждый раз.

Итак, "кеш" можно изменить, чтобы он не был недействительным столько, сколько вы ожидаете.

В моем проекте я периодически загружаю 500K записей в отсортированные наборы, а затем запускаю статистические отчеты только путем выполнения запросов по диапазонам по ним, что привело к тому, что время выполнения отчета составляло менее 2 секунд.