Стратегия шардинга данных в несколько миллионов строк в компании F6 Automobile Technology на основе Apache ShardingSphere

F6 Automobile Technology — компания, специализирующаяся на интернет-платформах и занимающаяся информатизацией вторичного рынка автомобилей. Она помогает авторемонтным компаниям (клиентам) создавать интеллектуальные системы управления для цифрового преобразования рынка автозапчастей.

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

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

Зачем нам нужно разделение данных?

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

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

Целью разделения данных является снижение нагрузки на базу данных и времени выполнения запросов. Кроме того, поскольку одна база данных часто имеет ограниченное количество соединений, когда показатель Queries Per Second (QPS) базы данных слишком высок, разделение баз данных, безусловно, необходимо, чтобы разделить нагрузку на соединения.

Во-вторых, еще одной важной причиной является обеспечение доступности. Если, к сожалению, произойдет авария в одной базе данных, мы, скорее всего, потеряем все данные и в дальнейшем это повлияет на все сервисы. Шардинг баз данных может минимизировать риск и негативное влияние на бизнес-сервисы. Обычно, когда объем данных в таблице превышает 2 ГБ или количество строк данных превышает 10 миллионов, не говоря уже о том, что данные также быстро растут, лучше использовать разделение данных.

Что такое шардинг данных?

В отрасли существует четыре распространенных типа ширдинга данных:

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

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

Горизонтальное разделение таблиц: распределение строк данных в таблицах по разным таблицам в соответствии с некоторыми правилами для уменьшения объема данных в отдельных таблицах и оптимизации производительности запросов. Что касается уровня базы данных, то он по-прежнему сталкивается с узкими местами.

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

Превосходные решения для разделения данных

1. Apache ShardingSphere-JDBC

Плюсы:

  • Поддерживается активным сообществом разработчиков с открытым исходным кодом. В настоящее время выпущена версия Apache ShardingSphere 5.0, и скорость итерации разработки высока.
  • Доказанная эффективность на примере многих успешных корпоративных приложений: такие крупные компании, как JD Technology и Dangdang.com, применяли ShardingSphere.
  • Простота развертывания: Sharding-JDBC может быть быстро интегрирован в любой проект без развертывания дополнительных служб.
  • Отличная совместимость: он может маршрутизироваться к одному узлу данных и отлично поддерживает SQL.
  • Отличная производительность и низкие потери: результаты тестов можно найти на сайте Apache ShardingSphere.

Минусы:

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

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

2. MyCat

Плюсы:

  • MyCat — это промежуточное программное обеспечение, размещенное между приложениями и базами данных для обработки данных и взаимодействия. Его нельзя воспринимать во время разработки, а интеграция MyCat не требует больших затрат.
  • Использование JDBC для подключения баз данных, таких как Oracle, DB2, SQL Server и MySQL.
  • Поддержка нескольких языков плюс простота развертывания и внедрения на различных платформах.
  • Высокая доступность и автопереключение, срабатывающее при сбое.

Минусы:

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

Конечно, существуют подобные решения, такие как Cobar, Zebra, MTDDL и TiDB, но, честно говоря, мы не тратили много времени на изучение других решений, поскольку решили использовать ShardingSphere, так как посчитали, что она отвечает потребностям компании.

Общий план компании F6 Automobile Technology

Исходя из бизнес-модели нашей компании, мы выбрали Client ID в качестве ключа Sharding Key, чтобы гарантировать, что данные о рабочих заказах одного клиента хранятся в одной таблице одной базы данных для конкретного клиента. Таким образом, можно избежать потери производительности, вызванной многотабличными коррелированными запросами; кроме того, даже если требуется шардинг нескольких баз данных, можно избежать перекрестных транзакций баз данных и перекрестных JOIN.

Среди баз данных ID клиента тип BIGINT(20) применяет UID (уникальный идентификационный номер, или мы называем его «геном») для обеспечения потенциального масштабирования базы данных в будущем; последние две цифры ID клиента являются его UID, поэтому, согласно правилу двойного масштабирования, максимум достигает 64 баз данных. Значения левых битов могут быть использованы для шардинга таблиц, которые можно разделить на 32 таблицы шардинга.

В качестве примера идентификатора клиента возьмем 10545055917999668983, а правила приведены ниже:

105450559179996689 83
Table sharding uid value % 32 database sharding uid value % 1
Войти в полноэкранный режим Выход из полноэкранного режима

Последние две цифры (т.е. 83) используются для шардинга базы данных, из которых временные данные шардируются только в библиотеку f6xxx, поэтому оставшееся значение равно 0. Позже, при увеличении объема данных, их можно будет распространить на несколько библиотек. Оставшееся значение 105450559179996689 используется для шардинга таблиц. В первый раз она делится на 32 отдельные таблицы, так что остатки по модулю соответствуют конкретным подписям таблиц шардинга — 0~31.

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

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

Шардирование таблиц

  1. Переход от JDBC к Sharding-JDBC для подключения источников данных
  2. Разъединить базы данных записи, а затем перенести коды
  3. Синхронизация исторических данных и инкрементных данных
  4. Переключение таблиц шардинга

Шардинг баз данных

  1. Перенесите базы данных, предназначенные только для чтения
  2. Миграция данных
  3. Переключение баз данных только для чтения
  4. Переключение баз данных, доступных только для записи

Детали разделения таблиц

Количество таблиц шардинга

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

Подготовка

— Замените базу данных & автоматический генератор идентификаторов таблиц

После шардинга таблиц мы больше не могли использовать автоматический генератор идентификаторов баз данных, поэтому нам нужно было найти приемлемое решение. У нас было два плана:

План 1: Использовать другие ключи, такие как snowflake.

План 2: самостоятельно реализовать инкрементный компонент (базу данных или Redis).

После сравнения двух решений и условий бизнеса мы решили выбрать План 2 и параллельно предоставили новое комплексное решение по генерации идентификаторов на уровне таблиц.

— Проверьте, все ли запросы выполняются с ключами шардов

Сейчас входы трафика микросервиса включают:

  • HTTP
  • Dubbo
  • Запланированное задание XXLJOB
  • Очередь сообщений (MQ)

После табличного шардинга, чтобы быстро находить шарды данных, все запросы должны нести свои ключи шардов.

— Разделение

  1. Разделите бизнес-системы каждого домена и используйте интерфейсы для взаимодействия с данными для чтения и записи.

  2. Удалите прямое соединение таблиц и используйте вместо него интерфейсы.

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

План выпуска серых шкал

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

План 1: Поддерживать два набора интерфейсов Mapper: один использует источники данных Sharding-JDBC для подключения к базам данных, а другой использует источники данных JDBC для подключения к базам данных. На сервисном уровне необходимо выбрать один из двух интерфейсов, основываясь на приведенной ниже диаграмме процесса принятия решения:

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

План 2 — Адаптивный план выбора маппера: один набор интерфейсов маппера имеет два источника данных и два набора реализаций. Исходя из конфигурации серого цвета, разные запросы клиентов будут проходить через разные реализации Mapper, а один сервис соответствует двум источникам данных и двум наборам менеджеров транзакций, и исходя из конфигурации серого цвета, запросы разных клиентов идут к разным менеджерам транзакций. Соответственно, мы используем несколько Mapper-сканеров MyBatis для генерации нескольких mapperInterfaces и параллельно генерируем mapperInterface для обертки. Класс обертки поддерживает hintManagert для автоматического выбора мапперов; менеджер транзакций аналогичен генерации класса обертки. Класс-обертка поддерживает hintManager для автоматического выбора различных менеджеров транзакций для управления транзакциями. Это решение фактически позволяет избежать вторжения, поскольку для кодов сервисного уровня существует только один интерфейс Mapper.

Переключатель соединений источников данных

Apache ShardingSphere уже перечислил на своем сайте некоторые грамматики, которые в настоящее время не поддерживаются Sharding-JDBC, но мы все еще обнаружили следующие проблемные SQL-запросы, которые не может обработать парсер Sharding-JDBC:

  • Подзапрос без ключа шарда.
  • Не поддерживаютсяInsert утверждения, значения которых включают cast ifnull now и другие функции.
  • Не поддерживаетсяON DUPLICATE KEY UPDATE.
  • По умолчанию выборка для обновления идет на подчиненную базу данных (проблема исправлена с версии 4.0.0.RC3).
  • Sharding-JDBC не поддерживает оператор ResultSet.first () из MySqlMapper с Optimistic Concurrency Control, используемый для запроса видения.
  • Нет такого утверждения и для пакетных обновлений.
  • Даже если UNION ALL не поддерживает план выпуска серого цвета, нам нужно только скопировать набор mapper.xml, и изменить его на основе синтаксиса Sharding-JDBC перед выпуском.

Синхронизация исторических данных

DataX — это автономный инструмент синхронизации данных Alibaba Group, который может эффективно синхронизировать разнородные источники данных, такие как MySQL, Oracle, SqlServer, Postgre SQL, HDFS, Hive, ADS, HBase, TableStore(OTS), MaxCompute(ODPS) и DRDS.

Фреймворк синхронизации данных DataX может абстрагировать синхронизацию различных источников данных в виде плагина Reader Plugin, который читает данные из источника данных, а затем в виде плагина Writer Plugin, который записывает данные на целевой объект. Теоретически, фреймворк DataX может поддерживать синхронизацию данных всех типов источников данных. Кроме того, экосистема плагинов DataX может позволить каждому вновь добавленному источнику данных немедленно взаимодействовать со старыми источниками данных.

Проверка синхронизации данных

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

Разделение чтения/записи и разделение таблиц

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

-Инкрементальная синхронизация данных

Для синхронизации инкрементных данных мы использовали другой проект синхронизации распределенных баз данных с открытым исходным кодом под названием Otter. Основываясь на разборе журнала инкрементальных данных базы данных, Otter может синхронизировать данные баз данных MySQL/Oracle в локальном компьютерном зале или удаленном компьютерном зале. Чтобы использовать Otter, необходимо обратить особое внимание на следующие советы:

  • Для баз данных MySQL у пользователя должен быть включен binlog, а его режим должен быть установлен как ROW.
  • Пользователь должен иметь разрешение на запрос binlog, поэтому ему необходимо подать заявку на это разрешение как пользователю otter.
  • Сейчас бинлог базы данных DMS хранится только 3 дня. В Otter пользователи могут самостоятельно определить начальную позицию синхронизации binlog и начальную точку инкрементальной синхронизации: сначала выберите slave-testDb на платформе SQL и используйте SQL-оператор «show master status» для запроса.

Примечание: результаты выполнения show master status ведущей и ведомой баз данных могут отличаться, поэтому при его установке необходимо получить результат выполнения ведущей базы данных. Мы считаем, что эта функция действительно полезна, потому что, когда синхронизация данных в Otter не удается, мы можем сбросить точки и синхронизировать снова с самого начала.

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

  • План переключения чтения/записи

Наш план переключения на серый цвет показан ниже:

Мы выбрали решение grayscale release, то есть необходимо было обеспечить обновление данных в реальном времени как в подтаблицах, так и в родительских таблицах. Поэтому все данные синхронизировались в двух направлениях: для клиентов с включенным grayscale release чтение и запись шли в подтаблицы, а данные синхронизировались с родительскими таблицами в реальном времени через Otter, а для клиентов с выключенным grayscale release чтение и запись шли в родительские таблицы, а данные синхронизировались с подтаблицами в реальном времени через Otter.

Детали шардинга базы данных

Подготовка

— Первичный ключ
Первичный ключ должен быть типа auto increment (таблицы шардинга должны иметь глобальный auto increment) или доступ к единственному сервису нумерации первичных ключей (server_id не зависит от БД). Генерация первичного ключа в таблице с автоинкрементом или генерация ключа uuid_short требует переключения.

— Хранимая процедура, функции, триггер и EVENT
Попытайтесь сначала удалить их, если они присутствуют; если их нельзя удалить, создайте их заранее в новых базах данных.

— Синхронизация данных
Для синхронизации данных используется DTS или sqldump (исторические данные) + otter (инкрементные данные).

— Процедура изменения базы данных
Чтобы избежать потенциальных проблем с производительностью и совместимостью, план изменения базы данных должен соответствовать двум критериям:

  • Переключение на серую шкалу: трафик постепенно переходит на RDS (Alibaba Cloud Relational Database Service, он же RDS), что позволяет наблюдать за производительностью базы данных в любое время.
  • Быстрый откат: достижение быстрого отката при возникновении проблем с минимальным влиянием на работу пользователей.

Статус-кво: четыре экземпляра приложения + одна главная база данных и две подчиненные базы данных.

Шаг 1: добавляем новый экземпляр приложения и переключаем его на RDS, записываем в главную базу данных dms или передаем ее, и данные в главной базе данных dms синхронизируются с rds в режиме реального времени.

Шаг 2: добавить еще три экземпляра приложения, и сократить 50% данных для записи в базу данных rds

Шаг 3: удалите трафик с четырех исходных экземпляров и считайте их в экземпляры rds, в то время как запись все еще идет в главную базу данных dms

Шаг 4: переключите главную базу данных на rds, и данные rds будут синхронизированы с главной базой данных dms, чтобы облегчить быстрый откат данных.

Шаг 5: Завершение

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

Шардинг и масштабирование

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

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

ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ

В: Иногда Otter получает данные бинлога, но эти данные не могут быть найдены в базе данных?

О:Чтобы сделать наш MySQL совместимым с репликами других нетранзакционных движков, мы добавили binlog на уровне сервера. Binlog может записывать все операции модификации двигателя, поэтому он может поддерживать функцию репликации для всех двигателей. Проблема заключается в потенциальной несогласованности между redo log и binlog, но MySQL использует свой внутренний механизм XA для устранения этой проблемы.

Шаг 1: Не выполняйте операции на InnoDB prepare, записывайте/синхронизируйте redo log и binlog.

Шаг 2: Сначала записывать/синхронизировать Binlog, а затем InnoDB commit (фиксация в памяти).

Конечно, начиная с версии 5.6, была добавлена групповая фиксация. Эта разработка в некоторой степени улучшает производительность ввода-вывода, но не меняет порядок выполнения.

После выполнения write/sync Binlog был записан, поэтому MySQL считает, что транзакция была зафиксирована и персистирована (теперь бинлог готов к отправке подписчикам). Даже если база данных рушится, транзакция может быть корректно восстановлена после перезагрузки MySQL. Однако до этого шага любой сбой в работе может привести к откату транзакции.

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

Причина, по которой может возникнуть проблема, заключается в том, что сначала отправляется binlog, а затем выполняется db commit. Для решения этой проблемы мы используем повторные запросы.

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

О:Стратегия маршрутизации ведущего/ведомого в Sharding-JDBC показана ниже:

Ведущие базы данных выбираются в следующих сценариях:

  • SQL-операторы, включающие блокировку, такие как select for update (из версии 4.0.0.RC3);
  • Не операторы SELECT;
  • Потоки, которые уже обратились к мастер-базам данных;
  • Коды, определяющие запросы к ведущим базам данных.

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

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

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

В: Как мы можем устранить сетевой трафик?
A:

  • http: используйте nginx для устранения восходящего потока;
  • dubbo: использовать модуль qos для выполнения offline/online команды;
  • xxljob: вручную ввести IP исполнителя для определения экземпляров;
  • MQ: используйте API, предоставляемый Alibaba Cloud, чтобы включить или отключить потребительский боб.

Ссылки на проект с открытым исходным кодом Apache ShardingSphere:

ShardingSphere Github
ShardingSphere Twitter
ShardingSphere Slack Channel

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *