Что делать при недоступности базы данных и какие есть методы борьбы с этим
Что проверяют
Понимаете ли вы, что отказ базы это не абстрактная неприятность, а конкретное поведение вашего кода: сколько потоков зависнет, что увидит пользователь, за сколько сервис поднимется обратно. Проверяют таймауты, пул и приёмы деградации, а не умение перечислить слова про отказоустойчивость.
Как отвечать
Первое требование: отказ должен быть быстрым. Без явных таймаутов поток висит на сокете минутами, пул выедается, и ложится всё приложение, а не одна функция. Настраиваются connectTimeout и socketTimeout в строке подключения JDBC, connectionTimeout и validationTimeout в пуле, время выполнения запроса через Statement.setQueryTimeout или настройку таймаута запроса в JPA.
Дальше слои защиты:
- повтор только для операций, которые безопасно повторять, с экспоненциальной паузой и разбросом. Повтор записи без ключа идемпотентности создаёт дубль;
- предохранитель: после серии отказов запросы перестают идти в базу и сразу возвращают ошибку, это даёт базе подняться, а сервису не копить очередь;
- деградация: читаемые данные отдаются из кэша с пометкой об устаревании, запись складывается в таблицу исходящих сообщений и досылается позже;
- разделение чтения и записи с переводом чтений на живую реплику.
Закончите наблюдаемостью: проба готовности должна отличать недоступную базу от мёртвого сервиса, иначе оркестратор перезапустит здоровые экземпляры и добавит нагрузки. Пользователю уходит понятная ошибка и код 503, а не пустой экран и бесконечный спиннер.
Где спотыкаются
Ставят бесконечные повторы без паузы. Когда база возвращается, все экземпляры приложения одновременно бьют в неё накопленной очередью и роняют снова. Спасают разброс задержки, ограничение попыток и предохранитель.
Второе: ловят Exception целиком и глотают его. Временный отказ соединения и ошибка данных требуют разного: первое имеет смысл повторять, второе повтор только размножит, а общий catch стирает разницу.
Третье: считают реплику и кэш бесплатной страховкой. Чтение с реплики отдаёт устаревшие данные, и это надо проговорить с заказчиком, а кэш без ограничения размера и времени жизни в момент аварии превращается в отдельную проблему с памятью.