Высокопроизводительная архитектура MySQL

MySQL

Обратите внимание на общедоступный номер: технический круг xy

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

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

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

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

Монолитные приложения и монолитные базы данных

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

В это время все запросы идут в одно приложение, а затем в одну и ту же базу данных:

单体

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

Распределенные приложения и разделение чтения и записи

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

В обычном бизнес-процессе работа с базой данных представляет собой не что иное, как два случая: чтение и запись. Как видно из предыдущих статей, индексация может значительно повысить производительность чтения, но повлияет на производительность записи. В большинстве интернет-проектов операции чтения обычно следуют за операциями записи. Согласно закону 28, операции записи составляют около 20 %, а операции чтения — около 80 %. В настоящее время, если все операции чтения и записи запрашиваются в одной и той же базе данных, нагрузка на базу данных относительно велика. Таким образом, мы можем сделать архитектуру разделения чтения и записи для базы данных:

主从同步

В соответствии с их потребностями, из множества баз данных.

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

Принцип репликации MySQL

MySQL реплицируется на основе двоичного журнала bin. Главный сервер записывает изменения данных в двоичный журнал, а главная библиотека отправляет события обновления в подчиненную библиотеку.

После получения события Slave открывает поток ввода/вывода. Поток ввода-вывода откроет общее соединение в Мастере, затем Мастер откроет поток дампа для выполнения операции копирования.

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

MySQL поддерживает следующие три метода репликации:

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

Репликация MySQL поддерживает множество режимов, в том числе «репликация мастер-мастер» и т. д., но при фактическом использовании рекомендуется использовать режим одного мастера и нескольких подчиненных.Двухмастерная архитектура может иметь проблемы, такие как конфликты идентификаторов или транзакции.

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

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

Подбиблиотека и подтаблица

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

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

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

Существует два способа разделения по горизонтали:

  • Подтаблица библиотеки: То есть таблица делится на несколько таблиц, но все равно помещается в одну и ту же базу данных. Например, по диапазону идентификаторов или по времени. Этот метод подходит для сценариев с горячими данными, таких как «Круг моментов».Как правило, недавние обращения к новым данным относительно велики, а обращения к старым данным относительно малы. Это позволяет выполнять сегментацию по временным диапазонам.
  • Подбиблиотека и подтаблица: Подтаблица подбазы данных предназначена для разделения таблицы на разные базы данных, и эти базы данных обычно находятся на разных узлах. Это также сформировало то, что мы часто называем «распределенной базой данных».

Ниже описаны два метода сегментации подтаблиц подбазы данных. Первый — разделить таблицу по диапазону значений или временному интервалу id, как и таблицу в библиотеке. Он также подходит для горячих данных, и его, естественно, легко масштабировать по горизонтали.Если вы хотите позже расширить емкость всего шардированного кластера, вам нужно только добавить узлы, и нет необходимости мигрировать данные других шардов. .

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

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

Проблемы, вызванные подбиблиотеками и подтаблицами

После подбазы данных и подтаблицы будут заданы следующие вопросы:

дела

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

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

join

После разделения базы данных и таблицы операция соединения станет очень проблематичной. Вот некоторые из наиболее распространенных решений:

  • Глобальные таблицы: то есть некоторые таблицы, от которых могут зависеть все модули в системе.Чтобы избежать запросов на соединение между базами данных, каждая база данных сохраняет копию.Эти данные обычно редко изменяются, поэтому не нужно беспокоиться о согласованности .

  • Антипарадигмальный дизайн: обмен места на время, избыточность данных. Запроса соединения можно избежать, но это может вызвать проблемы с синхронизацией данных. Например, если продавец меняет имя, нужно ли его синхронизировать с формой заказа? При этом рассматривается, следует ли использовать антипарадигмальный дизайн в соответствии с реальным бизнес-сценарием.

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

  • Сегментирование ER: Проще говоря, это размещение записей со связанными отношениями на одном и том же узле, чтобы можно было достичь локальных соединений и избежать соединений с перекрестным размещением. В это время, когда связанная таблица имеет отношение 1:1 или n:1 к основной таблице, она обычно делится в соответствии с первичным ключом id основной таблицы.

Пейджинг, сортировка и функции

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

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

конфликт первичного ключа

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

  • UUID: UUID прост в реализации, но имеет очевидные недостатки.Поскольку UUID очень длинный, он будет занимать много места для хранения, кроме того, будут проблемы с производительностью при создании индекса в качестве первичного ключа и выполнении запросов на основе В InnoDB нарушение UUID приведет к частому изменению местоположения данных, что приведет к пейджингу.
  • Распределенная схема генерации идентификаторов. На рынке существует множество распределенных схем генерации идентификаторов, таких как алгоритм снежинки Twitter, Leaf от Meituan, UidGenerator от Baidu и Redis для генерации идентификаторов.

решение

Эволюция архитектуры реляционной базы данных описана выше. Для MySQL встроенная поддержка распределенных не очень хороша, поэтому нам может понадобиться использовать некоторое промежуточное программное обеспечение базы данных, чтобы помочь. Такие как MyCat, Atlas и так далее. Автор лично интересуется Sharding-JDBC (сейчас обновлен до проекта Sharding-Sphere) и может изучить этот инструмент в будущем.

Кроме того, есть некоторые базы данных, которые изначально поддерживают распределение, например TiDB. TiDB совместим с синтаксисом MySQL и может быть легко перенесен из существующих баз данных MySQL в TiDB.

Кроме того, основные облачные платформы также поддерживают расширение базы данных. Например, облачная база данных RDS, такая как AWS и Alibaba Cloud, может легко настраивать master-slave, подбазу данных и подтаблицу.

Внимательно пишите статьи и делитесь ими с душой.

Персональный сайт:yasinshaw.com

Общедоступный номер: технический круг xy