Comments 23
Но теперь, в один прекрасный момент, случайно, система дала сбой и кеш рухнул. Ничего особенного – ведь кеш выбрали по требованию «высокая скорость чтения и записи, остальное неважно»… Вывод: высоконагруженные проекты в проде требуют от системы кеширования не только высокой скорости чтения и записи, но также сохранности данных и устойчивости к сбоям.
Можно поподробнее, что такое «кеш рухнул»? В чем конкретно это выражалось на клиентской и серверной частях и как долго продолжалось?
Но, здесь такой выбор оказался неудачным – под наш профиль нагрузки Hazelcast работает не просто медленно, а жутко медленно.
Интересно! Хотелось бы деталей касательно профиля.
Добавлю только, что прогрев кеша на продакшн-объемах данных — в редкой системе не приведет к выходу даунтайма за рамки SLA.
Можно здесь конкретизировать, в цифрах? Скорость прогрева кэша, каковы рамки SLA?
Однако ж, еще пара вопросов, если можно.
1) Какова была архитектура кеша до падения ( количество узлов, распределенность/репликация?)
2) 30Гб — что это за данные, вкратце? Описание товаров/складов/пользователей/счетов или что-то еще типа заказов/оплат/списаний?
Сейчас перешли на ReplicatedMap.
2. Здесь я указал данные по админке, которые нужны в ETL-расчетах — в основном для обеспечения вычислений по дельтам данных (флаги, что где проходило ранее). Немного про эту систему будет в следующей части статьи. И, возможно, подробно расскажу про наш дельта-процессор отдельным постом. Но это объемно и не скоро )
В чем конкретно это выражалось на клиентской и серверной частях и как долго продолжалось?
На проде мы такой неприятности не ловили. Подготовились благодаря тестам на uat.
Для Hazelcast версий 6-ти летней давности, при запуске в сетевом окружении того времени — узлы довольно часто теряли друг друга из вида, из-за чего кластер перестраивался. Потом кластер восстанавливался, но на некоторое время узел мог остаться без части данных. Потребовалось время, чтоб разобраться в настройках. Сейчас такой проблемы нет.
Хотелось бы деталей касательно профиля.
Профиль нагрузки в задачах админки того времени: put/get запросы в любой пропорции и за объектами любого размера.
Точной картинки спектра не сохранилось, но примерно:
* пропорция put/get в основном попадает в диапазон от 1:2 до 1:10, но есть несколько пиков в районе 1:100 и 1:10 000
* размер объектов — от небольших с 2-5 полями, до слонопотамов с 15 этажами вложенности (в сериализованном виде 10Кб, и несколько объектов поболее 100Кб)
на этом этапе Hazelcast кое-как устраивал. То есть, было плохо, в заданные рамки 10^5 RPS мы совершенно не укладывались, но была надежда, что можно что-то подкрутить, что-то вынести в специальный «горячий» кеш в памяти (тех самых итоговых слонопотамов, которых генерили в ETL). Была надежда, что потом еще что-нибудь в логике оптимизируем и будет нормально.
Но условия поменялись.
Добавилось очень, очень много запросов, когда по ключу нужно хранить только true/false.
И вот здесь стало совсем плохо.
То, что должны были выполнять за 10 минут — работало более 30 часов. То есть, через 30 часов тест прекратили, за сколько он отработал бы — осталось не известно.
Можно поподробнее, что такое «кеш рухнул»?
Я не автор, но видимо кеш просто очистился ;)
Если делается неперсистентный кеш, то он может разом пропасть. Т.е. неперсистентный кеш можно использовать для снижения времени ответа, но нельзя — для экономии железа. Или если хочется использовать для экономии железа — должна быть система прогревки кеша с допустимым даунтаймом сервиса или какая-то система деградации сервиса на время прогревки кеша. Но все это с потерей аптайма.
Персистентный кеш тут выглядит удобнее, но это уже и не кеш вовсе, а полноценная база с денормализованными данными и требованиями по эксплуатации и отказоустойчивости. Соответсвенно смотреть нужно не сколько на скорость, а на то, как осуществляется отказоустойчивость, как обеспечивается персистентность, есть ли шардирование хотя бы на уровне библиотеки, какой опыт эксплуатации базы в команде. Ну и проводить соответсвующие испытания — не "как быстро читает", а "что будет если мы этот вот сервер выключим".
Почему все так любят добавлять кеш к серверу? Это же сразу добавление в проект race-conditions и проблем с консистентностью данных. Советую посмотреть доклад на эту тему — https://www.youtube.com/watch?v=5ZjhNTM8XU8
https://martinfowler.com/bliki/TwoHardThings.html
Клааассика же. Но автору с командой эта задача, видимо, только предстоит :)
Все данные, которые отображаются на сайте и не являются хардкодом — попадают через базу, и почти все кешируются. Это и банеры, плашки, публикации, меню, настройки и все-все-все.
Как обстоят дела с распределением запросов по товарам на сайте именно сейчаc — не знаю, не могу сказать есть ли ярко выраженные пики (или наоборот, long-tail). Раньше не было.
Если все примерно так, то вам не кеш нужен, а нормальная модель в памяти. Чтения все из памяти, обновления тоже. Модель должна быть сделана так, чтобы при обновлении появлялся diff, который отправляется в очередь, откуда рассылается на другие узлы и записывается в базу. Нужно еще сделать механизм разруливания конфликтов, когда одни и туже вещь купили два раза. Если бы была база, то это решил бы ACID, а тут нужно будет понятие «over sale» иметь в предметной области.
Формирование заказа это резервация товара, фактически флажек в базе.
Да, все именно так, обработка заказа — это другая система.
Модель должна быть сделана так, чтобы при обновлении появлялся diff
Админка, которую разрабатывали, самая сложная ее часть — ровно про это — как генерить diff в данных подготовленных для сайта используя только diff по исходным данным. При этом схема трансформаций — это 100+ узлов и в 2 раза больше связей между ними (в среднем 1,9 связей на 1 узел). Чтоб с этим справиться в плане поддержки/доработки — был составлен движок. Внутренности этого движка активно производят вычисления и дают основную нагрузку по админке. Сложности с кешированием — словили как раз для промежуточных результатов этих вычислений.
Об этом проекте — будет отдельный пост.
Выбрали Apache Ignite по причинам:
1) sql (включая ddl) + полноценный acid, что фактически даёт Distributed RDBMS
2) .net interface
Как следствие linq provider, сервисы на нодах можно писать на шарпах
3) избыточность данных для восстановления при падении ноды
4) в последних версиях можно расширять data storage на HDD/SSD
Остальные фичи — ML, Streams, Messages на выбор не влияли.
Жаль только, что .Net и остальные — языки «второго сорта» и
поддержка основных фич = JVM.
AeroSpike? KeyDB ?
Как мы в Спортмастере выбирали систему кеширования. Часть 1