Pull to refresh

Опыт спасения кластера Cassandra

NoSQL
Sandbox
Мне довелось спасать ушедший в небытие кластер Cassandra. Это был интересный опыт, которым я бы хотел поделиться, ведь в штатной ситуации большинство баз данных работает одинаково, а вот уровень стресса при падении может отличаться очень сильно.



О проекте



Сервис, в котором использована Cassandra должен для каждого пользователя хранить N последних событий. События приходят намного чаще, чем пользователь может их прочитать и, в большинстве случаев, записанные данные никогда не будут прочитаны, а будут просто вытесненными более новыми событиями. В мире вообще пока не очень много баз данных, хорошо работающих во write-intensive задачах, но Cassandra одна из них. Запись в кластер (с минимальной консистентностью) намного быстрее чтения. Конечно помогает то, что выбирать данные надо только по первичному ключу — id пользователя.

Что пошло не так



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

nodetool ring
161594151652226679147006417055137150248
X1 Up 106.92 GB 38459616957251446947579138011358024346 |<--|
X2 Up 261.58 GB 87228834825681839886276714150491220347 | ^
X3 Up 268.08 GB 136691754424709629435450736264931173936 v |
X4 Up 148.58 GB 151190524462851319585265604946253553766 | ^
X5 Up 72.71 GB 161594151652226679147006417055137150248 |-->|


Размер жёсткого диска на всех пяти серверах был 260Гб. Две ноды упали, из-за кончившегося места на диске и весь кластер захлебнулся в нагрузке.

Документация же многократно предупреждает, что нельзя допускать автоматическое выделение сегментов кольца в продакшене. Приводит формулу и код на PHP для ручного расчёта токенов.

Реанимация



Во-первых, при выключенной Cassandra, с её файлами данных можно делать что угодно. Мы переместили один из тяжёлых и старых файлов (30Гб) на NFS и поставили на него symlink. Запустили кластер, проверили сервис — работает. Общее время починки с момента обнаружения проблемы — 15 минут. Почти всё это время ушло на перенос файла на NFS.

Во-вторых, я сразу включил кэширование в БД. Cassandra имеет довольно приличный механизм кэширования, значительно снижающий обращения к жёсткому диску. По крайней мере в нашем приложении попадания в кэш были между 80% и 90%.

nodetool setcachecapacity App Feeds 200000 1000000

На заметку: размер кэша задаётся в «записях», а не байтах. Надо правильно представлять себе размер средней записи, чтобы не промахнуться. Я, конечно же, промахнулся, выделил больше доступного и через несколько часов получил первую ноду, вылетевшую с Out Of Memory. Лечится простым перезапуском и более осторожным размером кэша.

Попытка лечения



Итак, сервис ожил, справляется с нагрузкой, но иметь несбалансированный кластер с частью данных на NFS долгое время, конечно же нельзя. После чтения документации была предпринята попытка использования команды nodetool move. Я пытался заставить её работать почти неделю. Суть проблемы была в том, что данные между нодами не перемещались. На ноде-источнике появлялся каталог streams, который содержал подготовленные для передачи данные, но сама передача (которую можно смотреть по команде notedool streams) всегда зависала. Иногда даже в самом начале.

Так я в первый раз столкнулся с багом 1221. Прочитав фикс, попытался обновиться на свежую версию, но тут меня настиг баг 1760. В итоге я всё-таки обновил кластер до 0.6.5, но сильно это не помогло. Кластер «застрял» в несбалансированном состоянии.

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

К моей огромной радости, к этому моменту руководство раскошелилось на обучающий семинар от Riptano. Это компания и есть Cassandra, они её разрабатывают и обеспечивают платную поддержку. На этом семинаре мне открылось дао Cassandra.

Дао Cassandra



Не пытайтесь ничего лечить. Падает — добейте, очистите, включить как новое. Именно так было сказано на семинаре. Именно этим объясняется рудиментарность инструментов для управления кластером. Дело в том, что по идее авторов управление заключается в двух основных операциях — 1) добавить ноду; 2) убрать ноду.

Именно таким образом мне в итоге и удалось починить кластер. Ноды были одна за другой убраны из кластера, очищены и запущены с правильно посчитанными токенами. Конечно мне пришлось посидеть за бумагой придумывая такой порядок перезапуска, который бы позволил обойтись без downtime. Это оказалась интересная, хотя и не очень сложная задачка по комбинаторике.

Без багов, конечно, не обошлось. Меня всё время преследовал 1676. Загружающаяся нода получала 50Гб своих новых данных и спокойно сидела дальше. Перезапуск сервиса приводил к получению следующих 50Гб. И так пока всё не придёт.

Заключение



Исправить кластер получилось. Моё мнение о Cassandra изменилось от «что за студенческая поделка, никаких инструментов нет» до «удивительно устойчивая БД». Фактически два месяца кластер работал с повреждёнными серверами — на двух скорость обращения к HDD была замедлена до скорости NFS. И при этом сервис в целом жил и пользователи не очень жаловались.

За это время я узнал много о внутренностях этой БД, пообщался с её создателями (удивительно отзывчивые и умные люди) и даже, ближе к концу процесса, получил удовольствие.
Tags:cassandranosql
Hubs: NoSQL
Total votes 77: ↑75 and ↓2+73
Views6.8K

Popular right now