Масштабирование до 100 миллионов пользователей. Кэшировать или не кэшировать?

Это вторая часть цикла «Масштабирование Wix до 100 миллионов пользователей». Вступление читайте тут.

Когда мы только запускали Wix, был использован стек Tomcat, Hibernate и Ehcache c базой данных MySQL и фронтендом на Flash. Почему мы выбрали этот стек? Да просто потому, что у нашего первого бэкенд-разработчика уже был опыт работы с ним. Частью этой архитектуры был Ehcache — отличная кэш-библиотека для Hibernate и JVM, которая создавала абстракцию в виде карты для кэша памяти и которая могла также быть сконфигурирована как распределенный кэш. Ehcache, в отличие от Memcached, запускается как процесс в JVM и в точности реплицирует состояние кэша для всех узлов кластера. Обратим внимание, что в то время (около 2006–2008 гг.) Encache все еще был независимым open source проектом и не был частью Terracotta (в рамках Terracotta модель репликации и дистрибуции может быть иной, но для данной статьи это не столь важно).

Аспекты использования кэша


31d5d5fb8e0d418492320f2cec336378.jpg

Поскольку у нас уже были реальные клиенты, мы установили два сервера Tomcat для обеспечения дополнительной надежности. Следуя правилам выстраивания архитектуры, мы установили распределенный Ehcache-кластер между серверами. Мы исходили из того, что MySQL работает медленно (как и любая другая SQL-система), а значит кэш оперативной памяти обеспечит гораздо более высокую скорость чтения и снизит нагрузку на базу данных.

Но что случится, когда мы столкнемся с проблемой данных, например, повреждением или замусориванием данных? Назовем такую проблему «некорректное состояние». Один подобный случай произошел, когда мы выкатили версию редактора Wix Editor, которая создавала неверное определение сайта. Симптомом этой проблемы стали поврежденные пользовательские сайты, т.е. пользователи не могли просматривать и редактировать свои сайты. К счастью, благодаря тому, что у нас была (и есть) очень большая пользовательская база, пользователи немедленно обнаружили эту проблему и сообщили о ней. Мы откатили проблемную версию и исправили поврежденные файлы определений в базе данных. К сожалению, даже после того, как мы внесли исправления во все места, где хранились эти данные, пользователи продолжали жаловаться на поврежденные сайты. Причина была в том, что мы просто исправили некорректное состояние, хранящееся в базе данных, забыв о том, что кэш тоже хранит копии наших данных, включая поврежденные документы.

Ehcache — это своего рода «черный ящик»: Java-библиотека без интерфейса SQL-запросов и без управляющего приложения для просмотра содержимого кэша. Поскольку у нас не было легкого способа «заглянуть» внутрь кэша, мы не могли его диагностировать и проанализировать, столкнувшись с повреждением данных (заметим, что у некоторых других решений для кэша есть управляющие приложения, которые превращают их в «белый ящик», но мы не работали ни с одним из них). Когда мы осознали, что некорректное состояние, по-видимому, сохранилось еще и в кэше, для решения проблемы нам понадобилось сперва исправить некорректное состояние в базе данных. Оба сервера приложений хранили некорректное состояние у себя в кэше, поэтому мы сначала остановили один из серверов, чтобы очистить кэш его памяти и снова запустить. Но так как кэш был распределенным, то даже после перезапуска сервера представление кэша его памяти было реплицировано со второго сервера приложений. В результате мы снова вернулись к некорректному состоянию. Перезапуск второго сервера на этом этапе ничем бы не помог, второй сервер получил бы репликацию некорректного состояния от первого. Единственным способом избавиться от этого некорректного состояния было остановить и перезапустить оба сервера, что привело к краткосрочному простою наших сервисов.

Как насчет инвалидации кэша?


Поскольку мы использовали Ehcache, у которого есть управляющий API с поддержкой инвалидации, мы могли бы написать специальный код, предписывающий обоим серверам считать кэш недействительным (инвалидационный переключатель). Но если бы мы не подготовили инвалидационный переключатель для работы с определенным типом данных, нам бы снова пришлось перезапускать оба сервера одновременно, чтобы избавиться от некорректного состояния. Конечно, мы могли бы сделать управляющее приложение для Ehcache, добавив возможность просмотра и инвалидации данных. Но в тот момент, когда нужно было принять это решение, мы задумались: «А нужен ли нам кэш на самом деле?».

Первым делом мы проверили статистику MySQL. Оказалось, что при правильном использовании MySQL операции чтения занимают доли миллисекунд даже для больших таблиц. Сегодня у нас есть таблицы, в которых свыше 100 миллионов строк, и мы читаем из них со скоростью в доли миллисекунд. Мы добились этого, обеспечив процесс MySQL достаточной памятью для работы с дисковым кэшем и читая отдельные строки по первичному ключу или индексу без соединения таблиц (JOIN). В конечном итоге мы поняли, что нам не нужен кэш. Фактически, в большинстве случаев, когда люди используют кэш, в нем на самом деле нет особой необходимости. Мы считаем, что кэш не является частью архитектуры. Это, скорее, одно из возможных решений для проблемы производительности, причем не самое лучшее.

Наши рекомендации по использованию кэша таковы:
1. Вам не нужен кэш.
2. Нет, правда, не нужен.
3. Если у вас сохраняются проблемы с производительностью, попробуйте разобраться с их источником. Что работает медленно? Почему оно работает медленно? Можно ли изменить архитектуру, чтобы работало не так медленно? Можно ли оптимизировать данные для чтения?

Если вам необходимо использовать кэш, обдумайте следующее:
• Как вы обеспечите инвалидацию кэша?
• Как вы будете просматривать данные в кэше («черный ящик» или «белый ящик»)?
• Как будет происходить холодный старт системы? Сможет ли система справиться с трафиком при пустом кэше?
• Какое ухудшение производительности влечет использование кэша?

Главный архитектор программного обеспечения конструктора для создания сайтов Wix,
Йоав Абрахами
Оригинал статьи: блог инженеров компании Wix

© Habrahabr.ru