книга сверху«Подтаблица подтаблицы базы данных для быстрого запуска одной статьи (обязательный курс)»,Эта статья длилась долго.Изначально ее планировалось закончить неделю назад.В итоге внутри семьи произошла внезапная кадровая перестановка,и руководство передало власть,а потом объявило,что я официально отец, а потом семейный статус упал на третье Имя, и на меня возложили долгосрочную задачу по уходу: заботиться о ребенке. Взгляните на наши красивые фотографии, стандартная маленькая леди симпатичная.
в видеSharding-JDBC
В первой статье серии фактических боевых действий о подбазе данных и подтаблицах мы рассмотрели базовые знания о подбазе данных и подтаблице в предыдущей статье и получили определенное представление о методе разделения подбазы данных и подтаблицы. таблица, давайте представим ее нижеSharding-JDBC
Framework и быстро создайте случай подбазы данных и подтаблицы, чтобы подготовить среду для объяснения последующих функциональных точек.
1. Введение в Sharding-JDBC
Sharding-JDBC
Это была структура подбазы данных и подтаблиц, используемая внутри Dangdang.com. Исходный код был открыт для внешнего мира только в 2017 году. улучшена, и теперь она была переименована.ShardingSphere
, 16 апреля 2020 года официально сталоApache
Проект высшего уровня Software Foundation.
С постоянной сменой версийShardingSphere
Основные функции также стали диверсифицированными. С самого начала версия SHARDING-JDBC 1.0 имела только Sharding Data Charding, чтобы Sharding-JDBC 2.0 версию начала поддерживать управление базы данных (Центр реестра, Центр конфигурации и т. Д.), А затем для версии Sharding-JDBC 3.0 добавлена распределенная транзакция (поддержка заAtomikos
,Narayana
,Bitronix
,Seata
), который теперь был преобразован в Sharding-JDBC 4.0.
Нынешняя ShardingSphere относится не только к определенному фреймворку, но и к экосистеме, этой экосистеме.Sharding-JDBC
,Sharding-Proxy
иSharding-Sidecar
Представлены три решения промежуточного программного обеспечения для распределенных баз данных с открытым исходным кодом.
ShardingSphere
предшественник былSharding-JDBC
, так что это самый классический и зрелый компонент во всей структуре.Начнем сSharding-JDBC
Фреймворк начинается с изучения подбазы данных и подтаблицы.
2. Основные концепции
В началеSharding-JDBC
Прежде чем подбаза данных и подтаблицы будут реализованы на практике, нам необходимо понять некоторые основные концепции подбазы данных и подтаблиц.
Фрагментация
Как правило, когда мы говорим о подбазе данных и подтаблице, большинство из них основаны на режиме горизонтальной сегментации (горизонтальная подбаза данных, подтаблица).t_order
Разделить для создания нескольких небольших таблиц данных с полностью согласованной структурой таблиц.t_order_0
,t_order_1
, t_order_n
, каждая таблица сохраняет только часть данных исходной большой таблицы при выполненииSQL
пройдет分库策略
,分片策略
Данные в разные базы данных, таблицы.
узел данных
Узел данных — это неделимая наименьшая единица данных (таблица) в подбазе данных и подтаблице, которая состоит из имени источника данных и таблицы данных, например, на рисунке выше.order_db_1.t_order_0
,order_db_2.t_order_1
представляет узел данных.
логическая таблица
Логическая таблица — это общий термин для группы таблиц с одинаковой логикой и структурой данных. Например, ставим форму заказаt_order
Разделить наt_order_0
··· t_order_9
等 10张表。 На этом этапе мы обнаружим, что в базе данных больше нет базы данных после подбазы данных и подтаблицы.t_order
Эта таблица вместоt_order_n
, но мы пишем в кодеSQL
все еще нажмитеt_order
написать. В настоящее времяt_order
Это эти разделенные столы逻辑表
.
реальный стол
Настоящая таблица указана вышеt_order_n
Физические таблицы, реально существующие в базе данных.
осколочный ключ
Поля базы данных для шардинга. мы будемt_order
После фрагментации таблицы при выполнении SQLorder_id
Метод по модулю используется для определения того, в какой таблице, в какой базе данных должны выполняться эти данные.order_id
полеt_order
Состояние шардинга таблицы.
Таким образом, связанные данные одного и того же порядка будут храниться в одной и той же таблице базы данных, что значительно повышает производительность поиска данных, не толькоsharding-jdbc
Он также поддерживает сегментирование на основе нескольких полей в качестве ключей сегментов.
Алгоритм фрагментации
Выше мы упоминали, что обычный шардинг может быть по модулю ключа шардинга, но это относительно простой вариант, и в реальной разработке мы также надеемся использовать>=
,<=
,>
,<
,BETWEEN
иIN
Если в качестве правил сегментирования для настройки логики сегментирования используются другие условия, необходимо использовать стратегию сегментирования и алгоритм сегментирования.
С точки зрения выполнения SQL сегментирование и сегментирование можно рассматривать как механизм маршрутизации, который направляет операторы SQL в нужную базу данных или таблицу данных и получает данные.Алгоритм сегментирования можно понимать как правило маршрутизации.
Давайте сначала посмотрим на отношения между ними. Стратегия сегментирования — это просто абстрактное понятие. Она состоит из алгоритма сегментирования и ключа сегментирования. Алгоритм сегментирования выполняет конкретную логику сегментирования данных.
Конфигурация стратегии сегментирования базы данных сегментирования и таблицы сегментирования относительно независима, и соответственно могут использоваться различные стратегии и алгоритмы Каждая стратегия может представлять собой комбинацию нескольких алгоритмов сегментирования Делайте логические выводы.
Уведомление: sharding-jdbc напрямую не обеспечивает реализацию алгоритма шардинга, и разработчикам необходимо реализовать его в соответствии со своим бизнесом.
sharding-jdbc
Обеспечивает 4 нарезанную арифметику:
1. Точный алгоритм шардинга
Алгоритм точного сегментирования (PreciseShardingAlgorithm) используется для одного поля в качестве ключа сегментирования в SQL.=
иIN
Для сегментирования с другими условиями стандартная стратегия сегментирования (StandardShardingStrategy
) использовать.
2. Алгоритм фрагментации диапазона
Алгоритм сегментирования диапазона (RangeShardingAlgorithm) используется для одного поля в качестве ключа сегментирования в SQL.BETWEEN AND
,>
,<
,>=
,<=
Для сегментирования с другими условиями стандартная стратегия сегментирования (StandardShardingStrategy
) использовать.
3. Составной алгоритм шардинга
Алгоритм комплексного шардирования (ComplexKeysShardingAlgorithm) используется для операций шардирования, где несколько полей используются в качестве ключей шардирования, и одновременно получаются значения нескольких ключей шардирования, а бизнес-логика обрабатывается в соответствии с несколькими полями. Требуется составная стратегия сегментирования (ComplexShardingStrategy
) использовать.
4. Алгоритм разделения подсказки
Алгоритм шардирования подсказок (HintShardingAlgorithm) немного отличается, в приведенном выше алгоритме мы все парсимSQL
Оператор извлекает ключ сегментирования и устанавливает стратегию сегментирования для сегментирования. Но иногда мы не используем какой-либо ключ сегментирования и стратегию сегментирования, но если мы хотим направить SQL в целевую базу данных и таблицу, нам необходимо вручную вмешаться, чтобы указать целевую базу данных и информацию о таблице SQL, что также называется принудительной маршрутизацией.
Стратегия шардинга
Говоря об алгоритме сегментирования выше, было сказано, что стратегия сегментирования является абстрактной концепцией, а фактическая операция сегментирования завершается алгоритмом сегментирования и ключом сегментирования.
1. Стандартная стратегия шардинга
Стандартная стратегия сегментирования применяется к одному ключу сегмента, эта стратегия поддерживаетPreciseShardingAlgorithm
иRangeShardingAlgorithm
Два алгоритма шардинга.
вPreciseShardingAlgorithm
требуется для обработки=
иIN
осколок.RangeShardingAlgorithm
опционально, для обработкиBETWEEN AND
,>
,<
,>=
,<=
Условный шардинг, если он не настроенRangeShardingAlgorithm
, условия в SQL будут обрабатываться по всему маршруту библиотеки.
2. Стратегия составного сегментирования
Составная стратегия разделения, та же поддержка оператора SQL=
,>
,<
,>=
,<=
,IN
иBETWEEN AND
операция шардинга. Разница в том, что он поддерживает несколько ключей сегментов, а конкретные детали распределения полностью реализуются разработчиком приложения.
3. Стратегия фрагментации выражения строки
Стратегия фрагментации строкового выражения, поддержка оператора SQL=
иIN
операция сегментирования, но поддерживает только один ключ сегмента. Эта стратегия обычно используется для простого шардинга, не требует специального алгоритма шардинга, а правила можно прописать прямо в конфигурационном файле.
t_order_$->{t_order_id % 4}
представлятьt_order
его полеt_order_id
Возьмите модуль и разделите его на 4 таблицы, а имена таблицt_order_0
прибытьt_order_3
.
4. Стратегия разделения подсказок
Стратегия сегментирования подсказки, соответствующая приведенному выше алгоритму сегментирования подсказки, путем указания ключа сегмента вместо fromSQL
Стратегия шардирования путем извлечения ключей шардов.
Распределенный первичный ключ
После разделения данных очень сложно сгенерировать глобально уникальный первичный ключ для разных узлов данных.Одна и та же логическая таблица (t_order
) в разных реальных таблицах (t_order_n
) между ключами автоинкремента, потому что они не могут воспринимать друг друга, что приводит к дублированию первичных ключей.
Хотя можно установить автоинкрементный первичный ключ初始值
и步⻓
Способ избежать конфликта идентификаторов, но это увеличит стоимость обслуживания, отсутствие целостности и масштабируемости. Если вам нужно увеличить количество таблиц сегментирования позже, вам нужно изменить размер шага таблиц сегментирования одну за другой, а стоимость эксплуатации и обслуживания очень высока, поэтому этот метод не рекомендуется.
Есть много способов реализовать распределенный генератор первичных ключей, вы можете обратиться к моей предыдущей статье "9 распределенных методов генерации ID".
Чтобы упростить начало работы, Apache ShardingSphere имеет встроенныйUUID
,SNOWFLAKE
Два распределенных генератора первичных ключей, по умолчанию использующих алгоритм Snowflake (snowflake
) для создания 64-битных целочисленных данных. Мало того, он также извлекает интерфейс распределенного генератора первичных ключей, что нам удобно для реализации собственного алгоритма генерации первичных ключей с автоинкрементом.
широковещательный стол
Широковещательная таблица: таблица, существующая во всех сегментированных источниках данных. Структура таблицы и данные в таблице абсолютно одинаковы во всех базах данных. Обычно это таблица-словарь или таблица конфигурации.t_config
, как только таблица настроена как широковещательная таблица, пока изменяется широковещательная таблица базы данных, данные широковещательной таблицы во всех источниках данных будут синхронизированы.
обязательный стол
Таблица привязки: те основные и подтаблицы, правила сегментирования которых совпадают. Например:t_order
бланк заказа иt_order_item
Список позиций заказа услуг, все в соответствии сorder_id
Поля фрагментированы, поэтому две таблицы связаны друг с другом.
Каково значение существования таблицы привязки?
Обычно используется в нашем бизнесеt_order
иt_order_item
Совместный запрос нескольких таблиц выполняется для других таблиц, но эти таблицы разбиты на N нескольких подтаблиц после подбазы данных и подтаблицы. Если отношение таблицы привязки не настроено, появится декартовский запрос ассоциации продукта, и будут сгенерированы следующие четыре элемента.SQL
.
SELECT * FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id
SELECT * FROM t_order_0 o JOIN t_order_item_1 i ON o.order_id=i.order_id
SELECT * FROM t_order_1 o JOIN t_order_item_0 i ON o.order_id=i.order_id
SELECT * FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id
Когда связанный запрос выполняется после настройки отношения таблицы привязки, если данные, сгенерированные соответствующими правилами сегментирования таблицы, непротиворечивы, они попадут в одну и ту же базу данных.t_order_0
иt_order_item_0
Таблицы могут быть связаны.
SELECT * FROM t_order_0 o JOIN t_order_item_0 i ON o.order_id=i.order_id
SELECT * FROM t_order_1 o JOIN t_order_item_1 i ON o.order_id=i.order_id
Уведомление: во время связанного запроса
t_order
Он действует как основная таблица для всего запроса на объединение. Все соответствующие расчеты маршрутизации используют только стратегию главной таблицы,t_order_item
Также используются расчеты, связанные с шардингом таблиц.t_order
условия, поэтому убедитесь, что ключи осколков между таблицами привязки точно такие же.
3. Трюки с JDBC
Нетрудно догадаться по названию,Sharding-JDBC
иJDBC
У него много работы, мы знаем, что JDBC — этоJava
Спецификация реляционной базы данных с языковым доступом предназначена для предоставления набора унифицированных стандартов для различных баз данных.Различные производители соблюдают этот стандарт и предоставляют свои собственные решения для реализации вызовов приложений.
Но на самом деле для разработчиков нас волнует только то, как вызывать JDBC API для доступа к базе данных, главное, чтобы он использовался корректно.DataSource
,Connection
,Statement
,ResultSet
Дождавшись интерфейса API, вы можете напрямую работать с базой данных. Поэтому, если вы хотите реализовать шардинг данных на уровне JDBC, вы должны расширить функции существующего API.Основываясь на этой идее, Sharding-JDBC переписывает спецификацию JDBC и полностью совместим со спецификацией JDBC.
к оригиналуDataSource
,Connection
Интерфейс расширен доShardingDataSource
,ShardingConnection
, а интерфейс операции сегментирования, доступный для внешнего мира, точно такой же, как интерфейс, представленный в спецификации JDBC.Если вы знакомы с JDBC, вы можете легко применить Sharding-JDBC для реализации сегментирования и сегментирования.
Так что это работает для любогоJDBC
изORM
кадр, например:JPA
,Hibernate
,Mybatis
,Spring JDBC Template
Или используйте JDBC напрямую. Идеально совместим с любым сторонним пулом соединений с базой данных, например:DBCP
,C3P0
,BoneCP
,Druid
,HikariCP
Поддерживаются почти все основные реляционные базы данных.
ТотSharding-JDBC
Как расширить эти интерфейсы?? Если вы хотите узнать ответ, мы начнем с исходного кода, а затем воспользуемся JDBC API вDataSource
Возьмите пример, чтобы увидеть, как его можно переписать и расширить.
источник данныхDataSource
Основной функцией интерфейса является получение объекта подключения к базе данных.Connection
, мы видим, что он предоставляет два метода для внутреннего подключения к базе данных и наследуетCommonDataSource
иWrapper
два интерфейса.
public interface DataSource extends CommonDataSource, Wrapper {
/**
* <p>Attempts to establish a connection with the data source that
* this {@code DataSource} object represents.
* @return a connection to the data source
*/
Connection getConnection() throws SQLException;
/**
* <p>Attempts to establish a connection with the data source that
* this {@code DataSource} object represents.
* @param username the database user on whose behalf the connection is
* being made
* @param password the user's password
*/
Connection getConnection(String username, String password)
throws SQLException;
}
вCommonDataSource
является корневым интерфейсом, который определяет хорошо понятный источник данных, в то время какWrapper
Интерфейс является ключом к расширению функции сегментирования JDBC.
Из-за разных поставщиков баз данных каждый из них может предоставлять некоторые расширенные функции, выходящие за рамки стандартного JDBC API, но эти функции не могут быть напрямую использованы стандартами, отличными от JDBC, иWrapper
Роль интерфейса заключается в переносе стандартного интерфейса, отличного от JDBC, предоставленного сторонним поставщиком, в стандартный интерфейс, т. е.适配器模式
.
Поскольку упоминается режим адаптера, позже он будет более подробным для облегчения понимания.
Шаблон адаптера является широко используемым шаблоном проектирования. Его функция заключается в преобразовании интерфейса класса в другой интерфейс, ожидаемый клиентом, чтобы два класса, которые не могут работать вместе из-за несоответствия (или несовместимости) интерфейса, могли работать вместе. .
Например, для прослушивания музыки в наушниках у меня круглая головка наушников, но разъем для мобильного телефона плоский. Если я хочу использовать наушники для прослушивания музыки, я должен использовать адаптер. Этот адаптер играет адаптивную роль.
Возьмите каштан: если мыTarget
в интерфейсеhello()
иword()
два метода.
public interface Target {
void hello();
void world();
}
Может повторяться из-за версии интерфейсаTarget
интерфейсword()
методы могут быть устаревшими или не поддерживаться,Adaptee
Категорияgreet()
метод заменитhello()
метод.
public class Adaptee {
public void greet(){
}
public void world(){
}
}
Но в это время еще много старых версийword()
используется, лучший способ решить эту проблему — создать адаптерAdapter
, значит подходитTarget
класс, который решает проблему совместимости, вызванную обновлением интерфейса.
public class Adapter extends Adaptee implements Target {
@Override
public void world() {
}
@Override
public void hello() {
super.greet();
}
@Override
public void greet() {
}
}
иSharding-JDBC
Он предоставляет нестандартный интерфейс JDBC, поэтому он также предоставляет аналогичную схему реализации и используетWrapper
Интерфейс используется для адаптации функции фрагментации данных. Помимо DataSource, этот интерфейс наследуют основные объекты, такие как Connection, Statement и ResultSet.
Мы приняли следующиеShardingDataSource
В исходном коде класса кратко рассматривается процесс реализации.На следующем рисунке показана блок-схема отношений наследования.
ShardingDataSource
класс это в оригиналеDataSource
На основе расширения функции фрагментированная оболочка маршрутизации SQL, контекст перезаписи SQL и механизм обработки набора результатов регистрируются во время инициализации, а также проверяется тип источника данных, поскольку он поддерживает несколько различных типов источников данных одновременно. . Кажется, я не вижу, как сюда вписаться, так что давайте посмотрим вверх.ShardingDataSource
унаследованный классAbstractDataSourceAdapter
.
@Getter
public class ShardingDataSource extends AbstractDataSourceAdapter {
private final ShardingRuntimeContext runtimeContext;
/**
* 注册路由、SQl重写上下文、结果集处理引擎
*/
static {
NewInstanceServiceLoader.register(RouteDecorator.class);
NewInstanceServiceLoader.register(SQLRewriteContextDecorator.class);
NewInstanceServiceLoader.register(ResultProcessEngine.class);
}
/**
* 初始化时校验数据源类型 并根据数据源 map、分片规则、数据库类型得到一个分片上下文,用来获取数据库连接
*/
public ShardingDataSource(final Map<String, DataSource> dataSourceMap, final ShardingRule shardingRule, final Properties props) throws SQLException {
super(dataSourceMap);
checkDataSourceType(dataSourceMap);
runtimeContext = new ShardingRuntimeContext(dataSourceMap, shardingRule, props, getDatabaseType());
}
private void checkDataSourceType(final Map<String, DataSource> dataSourceMap) {
for (DataSource each : dataSourceMap.values()) {
Preconditions.checkArgument(!(each instanceof MasterSlaveDataSource), "Initialized data sources can not be master-slave data sources.");
}
}
/**
* 数据库连接
*/
@Override
public final ShardingConnection getConnection() {
return new ShardingConnection(getDataSourceMap(), runtimeContext, TransactionTypeHolder.get());
}
}
AbstractDataSourceAdapter
Абстрактный класс в основном получает объекты подключения к базе данных, соответствующие разным типам источников данных.AutoCloseable
Интерфейсы для этих ресурсов могут автоматически отключаться после использования ресурсов (вызовclose
метод), затем посмотрите на унаследованный классAbstractUnsupportedOperationDataSource
.
@Getter
public abstract class AbstractDataSourceAdapter extends AbstractUnsupportedOperationDataSource implements AutoCloseable {
private final Map<String, DataSource> dataSourceMap;
private final DatabaseType databaseType;
public AbstractDataSourceAdapter(final Map<String, DataSource> dataSourceMap) throws SQLException {
this.dataSourceMap = dataSourceMap;
databaseType = createDatabaseType();
}
public AbstractDataSourceAdapter(final DataSource dataSource) throws SQLException {
dataSourceMap = new HashMap<>(1, 1);
dataSourceMap.put("unique", dataSource);
databaseType = createDatabaseType();
}
private DatabaseType createDatabaseType() throws SQLException {
DatabaseType result = null;
for (DataSource each : dataSourceMap.values()) {
DatabaseType databaseType = createDatabaseType(each);
Preconditions.checkState(null == result || result == databaseType, String.format("Database type inconsistent with '%s' and '%s'", result, databaseType));
result = databaseType;
}
return result;
}
/**
* 不同数据源类型获取数据库连接
*/
private DatabaseType createDatabaseType(final DataSource dataSource) throws SQLException {
if (dataSource instanceof AbstractDataSourceAdapter) {
return ((AbstractDataSourceAdapter) dataSource).databaseType;
}
try (Connection connection = dataSource.getConnection()) {
return DatabaseTypes.getDatabaseTypeByURL(connection.getMetaData().getURL());
}
}
@Override
public final Connection getConnection(final String username, final String password) throws SQLException {
return getConnection();
}
@Override
public final void close() throws Exception {
close(dataSourceMap.keySet());
}
}
AbstractUnsupportedOperationDataSource
выполнитьDataSource
интерфейс и унаследованноеWrapperAdapter
Внутри класса нет определенного метода, который действует только как мост, но он немного похож на пример шаблона адаптера, о котором мы говорили ранее.
public abstract class AbstractUnsupportedOperationDataSource extends WrapperAdapter implements DataSource {
@Override
public final int getLoginTimeout() throws SQLException {
throw new SQLFeatureNotSupportedException("unsupported getLoginTimeout()");
}
@Override
public final void setLoginTimeout(final int seconds) throws SQLException {
throw new SQLFeatureNotSupportedException("unsupported setLoginTimeout(int seconds)");
}
}
WrapperAdapter
представляет собой класс адаптера-оболочки, который реализуетWrapper
интерфейс, который имеет два основных методаrecordMethodInvocation
Для добавления методов и параметров для выполнения, иreplayMethodsInvocation
Затем добавленные методы и параметры выполняются посредством отражения. Если присмотреться, то можно увидеть, что используются оба метода.JdbcMethodInvocation
своего рода.
public abstract class WrapperAdapter implements Wrapper {
private final Collection<JdbcMethodInvocation> jdbcMethodInvocations = new ArrayList<>();
/**
* 添加要执行的方法
*/
@SneakyThrows
public final void recordMethodInvocation(final Class<?> targetClass, final String methodName, final Class<?>[] argumentTypes, final Object[] arguments) {
jdbcMethodInvocations.add(new JdbcMethodInvocation(targetClass.getMethod(methodName, argumentTypes), arguments));
}
/**
* 通过反射执行 上边添加的方法
*/
public final void replayMethodsInvocation(final Object target) {
for (JdbcMethodInvocation each : jdbcMethodInvocations) {
each.invoke(target);
}
}
}
JdbcMethodInvocation
Класс в основном применяет отражение через входящиеmethod
Методы иarguments
Параметр выполняет соответствующий метод, поэтому методы, отличные от JDBC, можно вызывать через API JDBC.
@RequiredArgsConstructor
public class JdbcMethodInvocation {
@Getter
private final Method method;
@Getter
private final Object[] arguments;
/**
* Invoke JDBC method.
*
* @param target target object
*/
@SneakyThrows
public void invoke(final Object target) {
method.invoke(target, arguments);
}
}
ТотSharding-JDBC
После расширения интерфейса JDBC API, что вы сделали в новой функции сегментирования?
Таблица делится на несколько подтаблиц после подбазы данных и подтаблицы и распределяется по разным базам данных.Без изменения исходного бизнес-SQL,Sharding-JDBC
Для правильного выполнения необходимо внести некоторые изменения в SQL.
Грубый процесс выполнения:SQL 解析
-> 执⾏器优化
-> SQL 路由
-> SQL 改写
-> SQL 执⾏
-> 结果归并
Он состоит из шести шагов, и давайте посмотрим, что делает каждый шаг вместе.
Разбор SQL
Процесс синтаксического анализа SQL разделен на два этапа: лексический анализ и синтаксический анализ.Например, в следующем SQL-запросе для пользовательских заказов лексический анализ используется для дизассемблирования SQL на неделимые атомарные единицы. Согласно словарю, предоставленному различными диалектами базы данных, эти единицы классифицируются по типам, таким как ключевые слова, выражения, переменные или операторы.
SELECT order_no,price FROM t_order_ where user_id = 10086 and order_status > 0
Затем синтаксический анализ преобразует разделенный SQL в абстрактное синтаксическое дерево и, проходя по абстрактному синтаксическому дереву, извлекает контекст, необходимый для фрагментации, а контекст содержит информацию о поле запроса (Field
), табличная информация (Table
),условия запроса(Condition
), сортировка информации (Order By
), группировка информации (Group By
) и информацию о разбивке на страницы (Limit
) и т. д., и отметьте позиции в SQL, которые, возможно, потребуется переписать.
Оптимизация исполнителя
Оптимизация исполнителя оптимизирует условия фрагментации SQL, обрабатывая такие ключевые слова, какOR
Этот неприятный вкус влияет на производительность.
SQL-маршрутизация
Маршрутизация SQL анализирует контекст сегментирования, сопоставляет политику сегментирования, настроенную пользователем, и создает путь маршрутизации. Простое понимание заключается в том, что мы можем рассчитать, в какой таблице и в какой базе данных должен выполняться SQL в соответствии с настроенной нами стратегией сегментирования, а маршрутизацию SQL можно различать в зависимости от того, есть ли ключ сегмента или нет.分片路由
и广播路由
.
Маршруты с ключами сегментов называются маршрутами сегментов и подразделяются на три типа: прямые маршруты, стандартные маршруты и маршруты декартовых произведений.
Стандартная маршрутизация
Стандартная маршрутизация является наиболее рекомендуемым и часто используемым методом разделения.Он применим к SQL, который не содержит реляционных запросов или содержит только реляционные запросы между таблицами привязки.
Когда оператор ключа SQL Shard=
результат маршрутизации попадет в одну библиотеку (таблицу), когда оператор разделения BETWEEN
или IN
Когда диапазон равен, результаты маршрутизации не обязательно попадают в уникальную базу данных (таблицу), поэтому логический SQL может в конечном итоге быть разделен на несколько реальных SQL для выполнения.
SELECT * FROM t_order where t_order_id in (1,2)
После обработки маршрутизации SQL
SELECT * FROM t_order_0 where t_order_id in (1,2)
SELECT * FROM t_order_1 where t_order_id in (1,2)
прямой маршрут
Прямая маршрутизация осуществляется с помощьюHintAPI
Метод разделения, который напрямую направляет SQL в таблицу базы данных, и прямую маршрутизацию можно использовать в сценариях, где ключи разделения не находятся в SQL, а также может выполнять произвольный SQL, включая подзапросы, пользовательские функции и другие сложные ситуации.
Напримерt_order_id
Поле является условным порядком запроса. В настоящее время есть надежда, что без изменения SQL, добавитьuser_id
Прямая маршрутизация может использоваться как условие фрагментации.
Декартова маршрутизация продукта
Декартова маршрутизация генерируется ассоциативным запросом между несвязанными таблицами.Если производительность запроса низкая, старайтесь избегать этого режима маршрутизации.
Маршруты без разделенных ключей также называются широковещательными маршрутами и могут быть разделены на пять типов: полная маршрутизация таблицы базы данных, полная маршрутизация базы данных, полная маршрутизация экземпляра, одноадресная маршрутизация и блокирующая маршрутизация.
Полная маршрутизация таблиц базы данных
Вся маршрутизация таблиц базы данных предназначена для базы данных.DQL
иDML
,а такжеDDL
и так далее, когда мы выполняем логическую таблицуt_order
Когда SQL, соответствующая реальная таблица во всех сегментированных библиотекахt_order_0
··· t_order_n
Выполнять по одному.
Полная библиотечная маршрутизация
Вся маршрутизация базы данных в основном предназначена для операций на уровне базы данных, таких как база данныхSET
Тип команды управления базами данных и контроль таких транзакций TCL утверждения.
Настроить библиотекуautocommit
После установки атрибута команда выполняется во всех соответствующих реальных библиотеках.
SET autocommit=0;
полная маршрутизация экземпляра
Полная маршрутизация экземпляра — это операция DCL для экземпляров базы данных (установка или изменение разрешений пользователя или роли базы данных), например: создание заказа пользователя, эта команда будет выполняться во всех реальных экземплярах базы данных, чтобы гарантировать, что пользователь заказа может нормально получить доступ к каждой базе данных. пример.
CREATE USER order@127.0.0.1 identified BY '程序员内点事';
Одноадресная маршрутизация
Одноадресная маршрутизация используется для получения реальной информации о таблице, такой как получение информации описания таблицы:
DESCRIBE t_order;
t_order
Настоящая таблицаt_order_0
···· t_order_n
, их структура описания точно такая же, нам нужно только один раз выполнить его на любой реальной таблице.
блокировать маршрутизацию
Используется для защиты операций SQL в базе данных, например:
USE order_db;
Эта команда не будет выполняться в реальной базе данных, потому чтоShardingSphere
Используется логическая схема (организация и структура базы данных), поэтому нет необходимости посылать команду на переключение базы данных в реальную базу данных.
SQL переписать
Перепишите SQL, разработанный на основе логических таблиц, в операторы, которые могут быть правильно выполнены в реальной базе данных. например, запросt_order
Таблица заказов, в нашей фактической разработке SQL основан на логической таблицеt_order
написано.
SELECT * FROM t_order
Но в реальной базе после ветки забиваютt_order
Таблица больше не существует, но разделена на несколько подтаблицt_order_n
Выполнение по исходному SQL явно нецелесообразно, если он разбросан по разным базам, в этом случае необходимо переписать имя логической таблицы в конфигурации подтаблицы на реальное имя таблицы, полученное после маршрутизации.
SELECT * FROM t_order_n
выполнение SQL
Безопасно и эффективно отправляйте перенаправленный и переписанный реальный SQL в базовый источник данных для выполнения. Но этот процесс предназначен не только для отправки SQL непосредственно в источник данных для выполнения через JDBC, но и для балансировки потребления создания соединения с источником данных и использования памяти, и он автоматически сбалансирует контроль ресурсов и эффективность выполнения.
Объединить результаты
Набор результатов с несколькими данными, полученный от каждого узла данных, объединяется в большой набор результатов и правильно возвращается запрашивающему клиенту, что называется объединением результатов. Синтаксис сортировки, группировки, разбиения на страницы и агрегирования в нашем SQL выполняется для объединенного набора результатов.
4. Быстрая практика
Ниже мы объединяемSpringboot
+ mybatisplus
Быстро создайте случай подбазы данных и подтаблицы.
1. Подготовка
Сначала выполните подготовительную работу, создайте две базы данныхds-0
,ds-1
, создать таблицы в двух библиотеках соответственноt_order_0
,t_order_1
,t_order_2
,t_order_item_0
,t_order_item_1
,t_order_item_2
,t_config
, что удобно для последующей проверки сценариев широковещательной таблицы и таблицы привязки.
Структура таблицы следующая:
t_order_0
форма заказа
CREATE TABLE `t_order_0` (
`order_id` bigint(200) NOT NULL,
`order_no` varchar(100) DEFAULT NULL,
`create_name` varchar(50) DEFAULT NULL,
`price` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
t_order_0
иt_order_item_0
взаимосвязанная таблица
CREATE TABLE `t_order_item_0` (
`item_id` bigint(100) NOT NULL,
`order_no` varchar(200) NOT NULL,
`item_name` varchar(50) DEFAULT NULL,
`price` decimal(10,2) DEFAULT NULL,
PRIMARY KEY (`item_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
широковещательный столt_config
`id` bigint(30) NOT NULL,
`remark` varchar(50) CHARACTER SET utf8 DEFAULT NULL,
`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`last_modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
ShardingSphere
Предусмотрено четыре метода настройки шарда:
-
Конфигурация кода Java
-
Yaml, конфигурация свойств
-
Конфигурация пространства имен Spring
-
Весенняя загрузка конфигурации
Для того, чтобы код выглядел более лаконичным и интуитивно понятным, он используется позже единообразно.properties
Способ настройки, импортshardingsphere
соответствующийsharding-jdbc-spring-boot-starter
иsharding-core-common
Пакет версии 4.0.0-RC1 для универсального использования.
2. Конфигурация фрагментации
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.0.0-RC1</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-core-common</artifactId>
<version>4.0.0-RC1</version>
</dependency>
Подготовка завершена (построение mybatis повторяться не будет), а затем мы будем интерпретировать информацию о конфигурации шарда одну за другой.
Сначала мы определяем два источника данныхds-0
,ds-1
и добавьте основную информацию об источнике данных соответственно.
# 定义两个全局数据源
spring.shardingsphere.datasource.names=ds-0,ds-1
# 配置数据源 ds-0
spring.shardingsphere.datasource.ds-0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds-0.driverClassName=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-0.url=jdbc:mysql://127.0.0.1:3306/ds-0?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
spring.shardingsphere.datasource.ds-0.username=root
spring.shardingsphere.datasource.ds-0.password=root
# 配置数据源 ds-1
spring.shardingsphere.datasource.ds-1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.ds-1.driverClassName=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds-1.url=jdbc:mysql://127.0.0.1:3306/ds-1?useUnicode=true&characterEncoding=utf8&tinyInt1isBit=false&useSSL=false&serverTimezone=GMT
spring.shardingsphere.datasource.ds-1.username=root
spring.shardingsphere.datasource.ds-1.password=root
После настройки источника данных добавьте стратегию подбазы данных и подтаблицы для таблицы, используйтеsharding-jdbc
Чтобы делать шардинг и шардинг, нам нужно задать правила шардинга для каждой таблицы отдельно.
# 配置分片表 t_order
# 指定真实数据节点
spring.shardingsphere.sharding.tables.t_order.actual-data-nodes=ds-$->{0..1}.t_order_$->{0..2}
actual-data-nodes
свойство указывает реальный узел данных шарда,$
является заполнителем, а {0..1} представляет фактическое количество разделенных таблиц базы данных.
ds-$->{0..1}.t_order_$->{0..2}
Выражение эквивалентно 6 узлам данных
- ds-0.t_order_0
- ds-0.t_order_1
- ds-0.t_order_2
- ds-1.t_order_0
- ds-1.t_order_1
- ds-1.t_order_2
### 分库策略
# 分库分片健
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.sharding-column=order_id
# 分库分片算法
spring.shardingsphere.sharding.tables.t_order.database-strategy.inline.algorithm-expression=ds-$->{order_id % 2}
Установите стратегию подбазы данных для таблицы, как указано выше.sharding-jdbc
Он предоставляет четыре стратегии сегментирования. Чтобы быстро построить, мы сначала реализуем простейшую стратегию сегментирования встроенных выражений. В следующей статье мы представим подробное использование и сценарии использования четырех стратегий сегментирования.
database-strategy.inline.sharding-column
атрибут database-strategy
Для стратегии подбиблиотеки inline
Для конкретной стратегии сегментирования sharding-column
Представляет фрагментацию.
database-strategy.inline.algorithm-expression
— конкретный алгоритм шардинга в рамках текущей стратегии,ds-$->{order_id % 2}
выражение означает даorder_id
Поле разделено по модулю на библиотеки. 2 – количество сегментированных библиотек. Разные стратегии соответствуют разным алгоритмам. Это также может быть наш пользовательский класс алгоритма сегментирования.
# 分表策略
# 分表分片健
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.sharding-column=order_id
# 分表算法
spring.shardingsphere.sharding.tables.t_order.table-strategy.inline.algorithm-expression=t_order_$->{order_id % 3}
# 自增主键字段
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
# 自增主键ID 生成方案
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
Конфигурация подстратегии таблицы и стратегии подбазы данных аналогична, разница в том, что подтаблица таблицы может быть настроена с помощьюkey-generator.column
иkey-generator.type
Установите первичный ключ автоинкремента и укажите схему генерации первичного ключа автоинкремента.SNOWFLAKE
иUUID
Двумя способами, а также алгоритмом генерации первичного ключа пользовательского класса, последует подробное объяснение.
# 绑定表关系
spring.shardingsphere.sharding.binding-tables= t_order,t_order_item
Таблицы, которые должны быть сегментированы в соответствии с одним и тем же ключом сегментации, могут быть связаны друг с другом, и при совместном запросе можно избежать декартовых запросов произведения.
# 配置广播表
spring.shardingsphere.sharding.broadcast-tables=t_config
Таблица вещания, откройте журнал парсинга SQL, вы можете ясно увидеть процесс парсинга фрагмента SQL
# 是否开启 SQL解析日志
spring.shardingsphere.props.sql.show=true
3. Проверьте шардинг
После настройки сегментирования нам не нужно изменять бизнес-код, мы можем напрямую добавлять, удалять, изменять и проверять бизнес-логику, а затем проверять эффект сегментирования.
В то же время мыt_order
,t_order_item
Таблица вставляет 5 записей заказов, первичный ключ не указанorder_id
,item_id
значение поля.
public String insertOrder() {
for (int i = 0; i < 4; i++) {
TOrder order = new TOrder();
order.setOrderNo("A000" + i);
order.setCreateName("订单 " + i);
order.setPrice(new BigDecimal("" + i));
orderRepository.insert(order);
TOrderItem orderItem = new TOrderItem();
orderItem.setOrderId(order.getOrderId());
orderItem.setOrderNo("A000" + i);
orderItem.setItemName("服务项目" + i);
orderItem.setPrice(new BigDecimal("" + i));
orderItemRepository.insert(orderItem);
}
return "success";
}
Увидев, что записи заказа были успешно распределены по разным библиотечным таблицам,order_id
Поле также автоматически генерирует идентификатор первичного ключа, и базовая функция сегментирования завершена.
таблица трансляцииt_config
Каков будет эффект от вставки части данных?
public String config() {
TConfig tConfig = new TConfig();
tConfig.setRemark("我是广播表");
tConfig.setCreateTime(new Date());
tConfig.setLastModifyTime(new Date());
configRepository.insert(tConfig);
return "success";
}
есть во всех библиотекахt_config
Все таблицы выполняют этот SQL, а режим широковещательной таблицы и подписки на широковещательную рассылку MQ очень похож, и все подписанные клиенты получат одно и то же сообщение.
Простая проверка операции SQL не удалась. Далее попробуем более сложный совместный запрос. Мы уже ставилиt_order
,t_order_item
Таблица задается как таблица привязки, и запрос выполняется непосредственно с таблицей.
Через лог консоли обнаруживается, что после парсинга логической таблицы SQL остается толькоt_order_0
иt_order_item_0
Таблица связана для генерации SQL.
Что, если они не связывают таблицы друг с другом? Удалитьspring.shardingsphere.sharding.binding-tables
попробуй.
Было обнаружено, что консоль разобрала 3 реальных табличных SQL-запроса и удалила их.order_id
После его повторного выполнения в качестве условия запроса в результате было проанализировано 9 фрагментов SQL, и был выполнен декартово произведение запроса. Таким образом, преимущества таблицы привязки очевидны по сравнению с ней.
V. Резюме
Вышеупомянутое промежуточное ПО для подбиблиотеки и подтаблицыsharding-jdbc
Вкратце разобрались с основными понятиями шардинга, быстро построили случай подбазы данных и подтаблицы, но это только первый шаг в практике подбазы данных и подтаблицы.В следующей статье мы подробно представить конкретное использование и использование четырех стратегий сегментирования.Сценарии (должны знать и знать), и объяснит пользовательские распределенные первичные ключи, транзакции распределенной базы данных, управление распределенными службами, десенсибилизацию данных и т. д.
кейс
GitHub
адрес:GitHub.com/Программист-NDS…
Разобраны и розданы друзьям сотни различных технических электронных книг. Подпишитесь на официальный аккаунт, чтобы ответить [666], чтобы получить его самостоятельно. Мы создали группу технического обмена с друзьями, чтобы обсуждать технологии и делиться технической информацией, стремясь вместе учиться и развиваться. Если вам интересно, присоединяйтесь к нам!