Обсуждение практики наступания на яму с подстолом

Java
Обсуждение практики наступания на яму с подстолом

предисловие

Многие люди спрашивали меня раньше: «Можете ли вы поделиться некоторыми практиками, связанными с подбазой данных и подтаблицей?» На самом деле, я не то чтобы не делюсь, но у меня действительно мало опыта 🤣; как и у большинства людей, они все еще находятся в теоретической стадии.

Но на этот раз есть что сказать.

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

И некоторым из наших предприятий необходимо выполнять связанные запросы или сообщать статистику; в этом контексте проблема больших таблиц становится более заметной (например, функция запроса выполняется несколько минут).

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

временный план

Из-за жесткого спроса и нехватки рабочей силы весь процесс обработки разбит на несколько этапов.

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

С этой целью мы нашли несколько таблиц с наибольшим объемом данных и обнаружили, что большая часть объема данных составляет около 7/8000 Вт, а некоторые превышают 100 миллионов.

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

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

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

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

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

Поэтому мы пришли к смелой идее: можно ли напрямую отбросить эту часть данных?

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

Итак, мы просто сделали следующее:

  • Измените имя исходной таблицы, например, добавив (_190416bak).
  • Создайте новую таблицу с тем же именем, что и исходная таблица.

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

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

План подтаблицы

Хотя предыдущий план может снять напряжение, он не может коренным образом решить проблему.

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

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

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

время

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

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

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

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

хэш

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

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

Поэтому мы планируем использоватьhashЭто относительно распространенный метод в отрасли, и здесь мы его повторять не будем.

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

Я также исследовал, прежде чем делать подтаблицуMyCATиsharding-jdbc(теперь обновлено доshardingsphere), и, наконец, учитывая удобство разработки и не увеличивая сложность эксплуатации и обслуживания, все же решено шардировать на уровне jdbc.

но по историческим причинам мы не очень хорошо интегрированыsharding-jdbc, но на основеshardingХарактеристики самореализованной стратегии подтаблицы.

Это просто и понятно:

int index = hash(sharding字段) % 分表数量 ;

select xx from 'busy_'+index where sharding字段 = xxx;

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

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

не какsharding-jdbcТаким же образом представлен метод запроса базы данных;SQL解析-->SQL路由-->执行SQL-->合并结果этот ряд процессов.

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

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

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

  • Например, отметка времени + случайное число могут удовлетворить большинство предприятий.
  • UUID, который легко сгенерировать, но невозможно отсортировать.
  • Алгоритм снежинки равномерно генерирует идентификатор первичного ключа.

Каждый может выбрать в соответствии со своей реальной ситуацией.

корректировка бизнеса

Поскольку мы не использовали сторонние компоненты sharding-jdbc, нет способа добиться низкой интрузивности кода; каждый бизнес-код, который включает подтаблицы, должен модифицировать базовый метод (то есть маршрут к правильной таблице).

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

Здесь также следует отметить небольшую деталь: количество подтаблиц должно быть в степени 2∧N, потому что в этом методе взятия подтаблиц по модулю даже данные, которые должны быть подтаблицей в будущем, будут быть как можно меньше.

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


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

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

Например, нужно ли запрашивать постранично и по дате данные из сотен миллионов? Есть ли смысл в таком бизнесе?

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

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

Иногда бывают и альтернативные сценарии:

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

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

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

проверять

После того, как код изменен и разработка завершена, более проблематично проверить, нормально ли работает подтаблица.

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

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

Онлайн-процесс

После прохождения теста и приемки это всего лишь 80% требований подтаблицы, а как выйти в интернет тоже головная боль.

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

перенос данных

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

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

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

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

Суммировать

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

Но наш последующий план состоит в том, чтобы изменить наше базовое подключение к данным (в настоящее время пакет jar, инкапсулированный нами, что затрудняет интеграцию sharding-jdbc) и в конечном итоге перейти наsharding-jdbc .

В итоге было сделано несколько выводов:

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

Наконец, добро пожаловать, чтобы оставить сообщение для обсуждения.

Ваши лайки и репост - лучшая поддержка для меня