В этом материале мы поговорим о практиках и ошибках при работе с разными СУБД, а также поделимся чек-листом от менеджера PaaS-продуктов Selectel Андрея Андронова.

Мы начнем с планов на проект и серверных комплектующих, пройдем через правила проектирования баз данных и доберемся до уровня доступности.

Слои работы с данными


Есть несколько уровней работы с данными, которые мы рассмотрим в материале:

  • Уровень серверных комплектующих, который обслуживает (хранит и вычисляет) данные. Все данные располагаются определенным способом, поскольку диски общаются только через драйвер и управляются через ОС.
  • Уровень системы управления базами данных. У каждой СУБД есть своя специфика и особенности реализации. Где-то удобнее организовать большое количество подключений и чтение, где-то удобнее часто записывать. Одни данные хранятся на дисках, другие — в оперативной памяти.
  • Уровень чтения и записи. В зависимости от профиля нагрузки следует организовать возможность быстро записывать и много читать. Например, в справочных приложениях доступ к данным и их чтению должен быть более приоритетным.
  • Уровень доступности. В зависимости от особенностей приложения проектируется архитектура базы данных.

Уровень серверных комплектующих: что использовать для БД и где размещать


Производительность баз данных напрямую связана с железом, которое выделено под работу этой системы.

Самые важные компоненты для БД:

  • частота процессора и количество ядер,
  • оперативная память и ее скорость,
  • тип и скорость диска.

Запросы на ресурсы серверов будут отличаться в зависимости от профиля нагрузки и типа базы данных. Например, для работы in-memory БД Redis обычно выделяют много оперативной памяти, чтобы обеспечить большое количество операций чтения/записи.

В реляционных БД нужны быстрые диски (SSD/NMVE) и различные варианты дисковых массивов RAID для ускорения дисковой подсистемы. При большом объеме информации, когда скорость не так важна, можно использовать меньше памяти и более медленные диски.

Лучшей практикой здесь будет всегда выделять ресурсы с запасом. Дело не только в том, чтобы покрывать запросы и следить за заполненностью дисков. В условиях недостаточности оперативной памяти или свободного места ОС может работать некорректно, что скажется на качестве предоставляемого сервиса.

Важно, чтобы база данных правильно работала на установленной ОС. От этого в определенной степени зависит производительность и поддержка функциональностей ядра по быстрой работе с данными и дисковой подсистемой.

Из этого вытекает следующий момент про хранение, обслуживание и масштабирование IT-инфраструктуры. Размещение в облаке поможет обеспечивать проект быстрым вертикальным и горизонтальным масштабированием. В on-premise реализации создать такую систему проблематично: нужно будет заранее закупать новые серверы или комплектующие, ждать их доставки.

Производительность и масштабирование


Готовые базы данных, как и другие облачные продукты, умеют быстро масштабироваться вне зависимости от направления (вертикальное/горизонтальное).

С ростом потребления вычислительных ресурсов или объема хранилища их можно быстро добавить любым из этих способов:

  • Вертикальное масштабирование (на запись) предполагает изменение виртуальных машин кластера, например, добавление новых дисков, процессоров.
  • Горизонтальное масштабирование (на чтение) предполагает создание новых реплик, которые также повышают отказоустойчивость БД.

Вместе с этим некоторые операции недоступны даже для облачных решений. Например, сокращение объема дискового пространства может повлечь за собой порчу или потерю данных, поэтому такая операция запрещена.



Уровень системы управления базами данных


С точки зрения клиента, самый сложный шаг — выбор СУБД для конкретного проекта.

Часто проблема решается на уровне компетенций. Используется та СУБД, в которой у команды есть опыт, чтобы работа не приносила сюрпризов.

Если отталкиваться от задач проекта, ситуация с выбором выглядит примерно так:

  • Если нужно работать с обычными структурированными данными, то чаще всего выбирают реляционные БД, такие как MySQL и PostgreSQL.
  • Если требуется супербыстрое хранение для хешей, авторизаций, то чаще используют БД типа Redis или Memcached.
  • Если предполагается работа с данными, которые привязаны к моменту времени, то используются time series БД. Например, TimescaleDB.
  • Если нужно работать с данными логов или аналитики, часто используется Clickhouse, Elasticsearch.
  • Если предполагается работа с большими данными, чаще всего выбирать приходится из PostgreSQL, Apache Cassandra, ScyllaDB.

В зависимости от профиля нагрузки проекту нужно иметь возможность быстро записывать или много читать. Для этого нужно, чтобы серверы, на которых расположена БД, были производительными. Также важно создавать реплики, с которых можно читать, чтобы снизить нагрузку на мастер. Это поможет мастеру «не отвлекаться» на непрофильные задачи.

У самих БД есть настройки по использованию ресурсов. Например, PostgreSQL
выделяют только часть памяти, а далее СУБД отдает память ОС для кэширования в оперативной памяти. Это позволяет минимизировать операции чтения с диска. В отличие от MySQL, который меньше полагается на кэш операционной системы и требует выделения большего объема оперативной памяти.

Важно определить метрики, за которыми нужно следить и отработать план реагирования на инциденты.

Уровень чтения и записи


Ключевой момент в проектировании архитектуры БД — возможность добавлять новые фичи по мере развития проекта. Например, в приложении появилась база знаний, поэтому к ней нужно обеспечить доступ на чтение. Менять базу данных или схему подключения с каждым релизом плохая практика. Кроме этого, не должна возникать ситуация, когда никто в команде не понимает, как поддерживать существующую систему.

Продумать вопрос схемы базы данных, распределения нагрузки (количество реплик) и партиционирования данных. Определить политики, необходимые роли и права пользователей.

Отказоустойчивость


Облачные базы данных предусматривают высокую доступность кластера базы данных. То есть автоматическое переключение на резервную ноду в случае недоступности мастера. Тогда приложение продолжит работать — для этого нужно несколько нод в кластере.

При самостоятельной настройке отказоустойчивого кластера, нужно создать его с несколькими нодами, которые выполняют страховочную функцию. Предусмотреть сервис оркестрации и механизм, предотвращающий split-brain.

Лучшей практикой считается, когда ноды кластера располагаются в разных зонах доступности и изолированы друг от друга. В таком случае удастся избежать сценария, когда резервные ноды падают одновременно из-за того, что виртуальные машины кластера находятся в одной стойке.

Подключение к БД


Для реализации высокодоступных систем есть разные варианты настройки сервисов. От виртуальных адресов, реализованных через corosync/pacemaker и keepalived, до организации mesh-сетей и использования сервисов типа Service Discovery (Consul). Также используются подходы из организации компьютерных сетей.

Подключение, например, можно организовать так, чтобы адрес был постоянным, а в случае отказа мастера БД средства оркестрации кластера базы данных переключат мастер на резервный хост и изменят DNS-запись, чтобы она вела на новый хост. Тогда клиенты смогут получить из DNS новый IP-адрес мастера и переподключиться.

Кроме этого, через DNS можно настроить доступ к репликам, чтобы снизить нагрузку на мастер-ноду. Это оптимизирует работу мастера для его прямых задач.

Пулинг соединений


В зависимости от типа базы данных и типа нагрузки, рассмотрите необходимость пулинга соединений.

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

В таких случаях используют пул соединений, чтобы ограничить число обслуживающих процессов. PostgreSQL не имеет встроенного пула соединений, поэтому приходится применять сторонние решения, такие как PgBouncer. При этом, как правило, один процесс на сервере поочередно выполняет транзакции разных клиентов. Это накладывает определенные ограничения на разработку приложений, которые необходимо учитывать.

Резервное копирование


Еще одна полезная практика — настройка автоматического резервного копирования. Оптимальный график может выглядеть так:

  • Раз в неделю — полное резервное копирование кластера.
  • Раз в день — инкрементальный бэкап, который содержит все изменения с момента последней копии.
  • Каждые 10 минут (или при накоплении определенного объема изменений) создаются WAL-файлы (binlog-файлы — для MySQL).

Последние позволяют восстанавливать базу в режиме Point-in-Time Recovery (восстановление в конкретную точку времени) и максимально обезопасить себя от потери данных. В зависимости от задач стоит рассмотреть разные сценарии и глубину резервного хранения.

В облачных базах данных процесс включает в себя механизмы резервного копирования, хранения и восстановления.

Мониторинг


Сбой в работе СУБД — это всегда большая проблема для сервиса. Если база данных стала недоступна, ее нужно максимально быстро реанимировать. Поэтому важно вести мониторинг и получать уведомления, чтобы отслеживать состояние и быстро узнавать о сбоях.

Мониторинг состояния базы данных обеспечивает поддержку высокой производительности и доступности. Своевременное реагирование на ошибки кластера позволит поддерживать бизнес-системы без простоев. В DBaaS обычно присутствует мониторинг в панели управления, а также возможность трансляции метрик в клиентские системы, чтобы отслеживать всю свою инфраструктуру в одном окне.

Уровень доступности


Работа с индексами


Самое важное — следить за оптимальными нагрузками, правильным построением запросов и индексов.

Индекс, который навешивается на таблицу, маркирует все значения. При этом NULL-значения обычно не нужны. Выход здесь простой: любая СУБД позволяет построить индекс, который не учитывает NULL-значения. Нужно пользоваться такой возможностью.

Размер индекса в этом случае уменьшится и будет содержать в себе только необходимое. То есть в поле могут быть значения от 1 до 100, но запрос делается чаще всего по значениям 1, 2, 3, поэтому можно легко проиндексировать только эти значения. Тогда индекс получится небольшим и будет быстрее работать. Разницу между полным индексом и частичным можно увидеть сразу в системе мониторинга: время отклика резко сократится.

Все индексы со временем разрастаются, поэтому нужно периодически их сжимать и чистить, чтобы они работали эффективно.

Индексы имеют свои правила и ограничения: не стоит навешивать индексы при создании таблицы. Нужно сначала дождаться результата, а потом оценить логику и план выполнения запроса.

Кластеризованные индексы применяются для работы с датами.

Например, есть запрос о поиске всех строк с 1 по 25 ноября. Если вы используете на дате кластеризованный индекс, то строки будут идти подряд. Это значит, что СУБД сможет их быстро прочитать с диска. Это оптимизирует количество операций и уменьшит время отклика.

Функциональный индекс универсален для всех СУБД.

Так можно индексировать данные по какой-либо функции. Индекс подходит для задач, когда вам нужно найти, например, все события за определенную дату, при этом год не имеет значения.

Индексы по числам эффективнее, чем по строкам.

Таким способом лучше хранить все числовые данные (номера телефонов, страховки, ИНН), потому что индекс будет занимать меньше места. Этим способом можно добиться оптимального кэширования и быстрой выдачи.

Чек-лист по работе с СУБД


  • Проверьте, как устроена утилизация CPU и как расходуется память.
  • Проверьте запас ресурсов. Дисковое пространство должно быть в избытке, чтобы не допустить потерю данных.
  • Проверьте организацию подключения к СУБД. Задействуйте реплики для чтения.
  • Проверьте график бэкапов и комбинируйте их типы, чтобы максимально обезопасить систему от даунтаймов. Периодически проводите восстановление данных из бэкапа для проверки консистентности.
  • Проверьте, как строятся запросы и можно ли их оптимизировать.
  • Рассмотрите возможность подключения пулера соединений для уменьшения потребляемых ресурсов.
  • Составьте план по обеспечению высокой доступности сервиса.
  • Организуйте мониторинг и реакции на ошибки и аварии.

Что в итоге


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

Следуйте чек-листу, своевременно масштабируйте кластеры и проводите регулярный мониторинг, чтобы отслеживать аномальные ситуации до того, как они смогут нанести урон вашему приложению.

Читайте больше о базах данных в нашем блоге:

DBaaS: что такое облачные базы данных
Как работает СУБД Redis
Книги по SQL: что почитать новичкам и специалистам