над«Быстрый старт Sharding — JDBC Middleware Sharding — JDBC (обязательный курс)»введен вsharding-jdbc
Основная концепцияSQL
Различные операторы, которые появляются в>
,<
,between and
,in
д., чтобы выбрать соответствующую стратегию разделения данных.
Прежде чем продолжить, я задам вопросы и ответы. Маленький партнер задал вопрос в частном порядке два дня назад и сказал:
Что, если некоторые из моих таблиц являются подтаблицами базы данных, а другая часть не является подтаблицей базы данных? Как я могу получить к нему доступ в обычном режиме?
Это типичная проблема.Мы знаем, что подтаблицы подбазы данных предназначены для некоторых таблиц, объем данных которых продолжает значительно расти, таких как пользовательские таблицы, таблицы заказов и т. д., а не для сегментирования всех таблиц по всем направлениям. Итак, как разделить несегментированную таблицу и сегментированную таблицу, обычно есть два решения.
- Строго разделить библиотеку функций, отделить сегментированную библиотеку от не сегментированной библиотеки и переключать доступ к источнику данных по требованию в бизнес-коде.
- Установите источник данных по умолчанию на
Sharding-JDBC
Например, если правила сегментирования не установлены для нешардированных таблиц, они не будут выполняться, потому что правила маршрутизации не могут быть найдены.В настоящее время мы устанавливаем источник данных по умолчанию и всегда обращаемся к библиотеке по умолчанию, когда правила не найдены.
# 配置数据源 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://47.94.6.5: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
# 默认数据源,未分片的表默认执行库
spring.shardingsphere.sharding.default-data-source-name=ds-0
В этой статье мы попрактикуемся в использовании четырех стратегий сегментирования для конкретных сценариев использования SQL и выполним некоторые приготовления перед началом.
-
Стандартная стратегия разделения
-
Составная стратегия шардинга
-
стратегия сегментирования выражений строк
-
Стратегия разделения подсказок
Готов к работе
Сначала создайте две базы данных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
6 таблиц, давайте посмотрим, как это применить в разных сценарияхsharding-jdbc
4 стратегии шардинга.
t_order_n
Структура таблицы следующая:
CREATE TABLE `t_order_0` (
`order_id` bigint(200) NOT NULL,
`order_no` varchar(100) DEFAULT NULL,
`user_id` bigint(200) NOT 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_item_n
Структура таблицы следующая:
CREATE TABLE `t_order_item_0` (
`item_id` bigint(100) NOT NULL,
`order_id` bigint(200) 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;
Стратегия шардинга делится на分表策略
а также分库策略
, реализуют алгоритм шардинга в принципе одинаково, разница в паре библиотекds-0
,ds-1
, парный столt_order_0
··· t_order_n
ждать обработки.
Стандартная стратегия разделения
сцены, которые будут использоваться: в операторе SQL>
,>=
, <=
,<
,=
,IN
а такжеBETWEEN AND
оператор, эта стратегия сегментирования может быть применена.
Стандартная стратегия разделения (StandardShardingStrategy
), он поддерживает сегментирование базы данных и таблиц только на основе одного ключа сегмента (поля) и предоставляет два алгоритма сегментирования.PreciseShardingAlgorithm
(точный шардинг) иRangeShardingAlgorithm
(разделение диапазона).
При использовании стандартной стратегии сегментирования точный алгоритм сегментирования является обязательным алгоритмом для SQL, содержащего=
а такжеIN
сегментация; алгоритм сегментации диапазона является необязательным и используется дляBETWEEN AND
Фрагментарная обработка.
Один раз мы не настраиваем алгоритм сегментации диапазона, и снова используется SQL
BETWEEN AND
илиlike
и т. д., то SQL будет выполняться один за другим на пути маршрутизации всей базы данных и таблиц, а производительность запросов будет очень низкой, требующей особого внимания.
Следующая пользовательская реализация精准分片算法
а также范围分片算法
.
1. Точный алгоритм шардинга
1.1 Алгоритм точного разделения базы данных
Методы реализации пользовательских точных алгоритмов секционирования базы данных и таблиц примерно одинаковы, и оба должны быть реализованы.PreciseShardingAlgorithm
интерфейс и переопределитьdoSharding()
метод, но конфигурация немного отличается, и это просто пустой метод, мы должны сами разобраться с логикой подбиблиотеки и подтаблицы.То же самое касается и других стратегий шардинга..
SELECT * FROM t_order where order_id = 1 or order_id in (1,2,3);
Затем мы реализуем точную стратегию секционирования базы данных через состояние разделов.order_id
Метод по модулю (как его реализовать — зависит от ваших предпочтений) вычисляет, в какую библиотеку следует роутить SQL, а рассчитанная информация о библиотеке шардинга будет храниться в контексте шардинга, что удобно для использования в последующих таблицах шардинга.
/**
* @author xiaofu 公众号【程序员内点事】
* @description 自定义标准分库策略
* @date 2020/10/30 13:48
*/
public class MyDBPreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
@Override
public String doSharding(Collection<String> databaseNames, PreciseShardingValue<Long> shardingValue) {
/**
* databaseNames 所有分片库的集合
* shardingValue 为分片属性,其中 logicTableName 为逻辑表,columnName 分片健(字段),value 为从 SQL 中解析出的分片健的值
*/
for (String databaseName : databaseNames) {
String value = shardingValue.getValue() % databaseNames.size() + "";
if (databaseName.endsWith(value)) {
return databaseName;
}
}
throw new IllegalArgumentException();
}
}
вCollection<String>
Параметры последовательно используются в нескольких стратегиях сегментирования, а значением является набор всех сегментированных библиотек при сегментировании.databaseNames
, который представляет собой набор всех сегментированных таблиц в соответствующей сегментированной библиотеке при сегментировании.tablesNames
;PreciseShardingValue
является атрибутом фрагментации, гдеlogicTableName
логическая таблица,columnName
ключ осколка (поле),value
Значение ключа сегмента, полученное из SQL.
а такжеapplication.properties
Нужно только изменить имя стратегии подбазы данных в файле конфигурацииdatabase-strategy
стандартный режимstandard
, алгоритм шардингаstandard.precise-algorithm-class-name
Это путь к классам настроенного алгоритма точной подбиблиотеки.
### 分库策略
# 分库分片健
spring.shardingsphere.sharding.tables.t_order.database-strategy.standard.sharding-column=order_id
# 分库分片算法
spring.shardingsphere.sharding.tables.t_order.database-strategy.standard.precise-algorithm-class-name=com.xiaofu.sharding.algorithm.dbAlgorithm.MyDBPreciseShardingAlgorithm
1.2 Алгоритм точного деления таблицы
Также реализован точный алгоритм разбиения таблицыPreciseShardingAlgorithm
интерфейс и переопределитьdoSharding()
метод.
/**
* @author xiaofu 公众号【程序员内点事】
* @description 自定义标准分表策略
* @date 2020/10/30 13:48
*/
public class MyTablePreciseShardingAlgorithm implements PreciseShardingAlgorithm<Long> {
@Override
public String doSharding(Collection<String> tableNames, PreciseShardingValue<Long> shardingValue) {
/**
* tableNames 对应分片库中所有分片表的集合
* shardingValue 为分片属性,其中 logicTableName 为逻辑表,columnName 分片健(字段),value 为从 SQL 中解析出的分片健的值
*/
for (String tableName : tableNames) {
/**
* 取模算法,分片健 % 表数量
*/
String value = shardingValue.getValue() % tableNames.size() + "";
if (tableName.endsWith(value)) {
return tableName;
}
}
throw new IllegalArgumentException();
}
}
Когда стол разделенCollection<String>
Параметр — рассчитанная выше библиотека шардинга и соответствующий набор всех таблиц шардингаtablesNames
;PreciseShardingValue
является атрибутом фрагментации, гдеlogicTableName
логическая таблица,columnName
ключ осколка (поле),value
Значение ключа сегмента, полученное из SQL.
application.properties
В файле конфигурации также нужно только изменить имя стратегии подтаблицы.database-strategy
стандартный режимstandard
, алгоритм шардингаstandard.precise-algorithm-class-name
Это путь к классам настроенного точного алгоритма секционирования таблицы.
# 分表策略
# 分表分片健
spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.sharding-column=order_id
# 分表算法
spring.shardingsphere.sharding.tables.t_order.table-strategy.standard.precise-algorithm-class-name=com.xiaofu.sharding.algorithm.tableAlgorithm.MyTablePreciseShardingAlgorithm
В этом нетрудно убедиться, реализация пользовательской подбазы данных и табличных подалгоритмов в основном одинакова, поэтому позже мы продемонстрируем только подбазу данных.
2. Алгоритм фрагментации диапазона
сцены, которые будут использоваться: когда используется поле ключа фрагмента в нашем SQLBETWEEN AND
Оператор будет использовать этот алгоритм и будет обрабатывать сегментирование и логику сегментирования в соответствии со значением диапазона значений ключа сегментирования, заданным в SQL.
SELECT * FROM t_order where order_id BETWEEN 1 AND 100;
Необходимо реализовать собственный алгоритм разделения диапазонаRangeShardingAlgorithm
интерфейс, переопределениеdoSharding()
метод, ниже я рассчитываю логику каждой подбиблиотеки и подтаблицы, проходя интервал ключ-значение осколка.
/**
* @author xinzhifu
* @description 范围分库算法
* @date 2020/11/2 12:06
*/
public class MyDBRangeShardingAlgorithm implements RangeShardingAlgorithm<Integer> {
@Override
public Collection<String> doSharding(Collection<String> databaseNames, RangeShardingValue<Integer> rangeShardingValue) {
Set<String> result = new LinkedHashSet<>();
// between and 的起始值
int lower = rangeShardingValue.getValueRange().lowerEndpoint();
int upper = rangeShardingValue.getValueRange().upperEndpoint();
// 循环范围计算分库逻辑
for (int i = lower; i <= upper; i++) {
for (String databaseName : databaseNames) {
if (databaseName.endsWith(i % databaseNames.size() + "")) {
result.add(databaseName);
}
}
}
return result;
}
}
то же, что и вышеCollection<String>
При сегментировании базы данных и таблицы он представляет собой имя сегментированной базы данных и набор имен таблиц соответственно.RangeShardingValue
Здесь метод значения немного отличается,lowerEndpoint
представляет начальное значение,upperEndpoint
представляет собой пороговое значение.
С точки зрения конфигурации, поскольку алгоритм сегментирования диапазона и алгоритм точного сегментирования используются в рамках стандартной стратегии сегментирования, вам нужно только добавитьrange-algorithm-class-name
Вы можете настроить путь к классам алгоритма разделения диапазона.
# 精准分片算法
spring.shardingsphere.sharding.tables.t_order.database-strategy.standard.precise-algorithm-class-name=com.xiaofu.sharding.algorithm.dbAlgorithm.MyDBPreciseShardingAlgorithm
# 范围分片算法
spring.shardingsphere.sharding.tables.t_order.database-strategy.standard.range-algorithm-class-name=com.xiaofu.sharding.algorithm.dbAlgorithm.MyDBRangeShardingAlgorithm
Составная стратегия шардинга
сцены, которые будут использоваться: в операторе SQL>
,>=
, <=
,<
,=
,IN
а такжеBETWEEN AND
и другие операторы, разница в том, что составная стратегия сегментирования поддерживает операции с несколькими ключами сегментов.
Далее реализуем одновременныйorder_id
,user_id
Два поля используются в качестве ключей сегментирования для настройки составной стратегии сегментирования.
SELECT * FROM t_order where user_id =0 and order_id = 1;
Давайте сначала изменим исходную конфигурацию.complex.sharding-column
переключиться наcomplex.sharding-columns
множественное число, добавить один к ключу осколкаuser_id
, название стратегии сегментирования изменено наcomplex
,complex.algorithm-class-name
Заменено нашим собственным составным алгоритмом сегментирования.
### 分库策略
# order_id,user_id 同时作为分库分片健
spring.shardingsphere.sharding.tables.t_order.database-strategy.complex.sharding-column=order_id,user_id
# 复合分片算法
spring.shardingsphere.sharding.tables.t_order.database-strategy.complex.algorithm-class-name=com.xiaofu.sharding.algorithm.dbAlgorithm.MyDBComplexKeysShardingAlgorithm
Индивидуальная стратегия составного сегментирования, которая будет реализованаComplexKeysShardingAlgorithm
интерфейс, повторноdoSharding()
метод.
/**
* @author xiaofu 公众号【程序员内点事】
* @description 自定义复合分库策略
* @date 2020/10/30 13:48
*/
public class MyDBComplexKeysShardingAlgorithm implements ComplexKeysShardingAlgorithm<Integer> {
@Override
public Collection<String> doSharding(Collection<String> databaseNames, ComplexKeysShardingValue<Integer> complexKeysShardingValue) {
// 得到每个分片健对应的值
Collection<Integer> orderIdValues = this.getShardingValue(complexKeysShardingValue, "order_id");
Collection<Integer> userIdValues = this.getShardingValue(complexKeysShardingValue, "user_id");
List<String> shardingSuffix = new ArrayList<>();
// 对两个分片健同时取模的方式分库
for (Integer userId : userIdValues) {
for (Integer orderId : orderIdValues) {
String suffix = userId % 2 + "_" + orderId % 2;
for (String databaseName : databaseNames) {
if (databaseName.endsWith(suffix)) {
shardingSuffix.add(databaseName);
}
}
}
}
return shardingSuffix;
}
private Collection<Integer> getShardingValue(ComplexKeysShardingValue<Integer> shardingValues, final String key) {
Collection<Integer> valueSet = new ArrayList<>();
Map<String, Collection<Integer>> columnNameAndShardingValuesMap = shardingValues.getColumnNameAndShardingValuesMap();
if (columnNameAndShardingValuesMap.containsKey(key)) {
valueSet.addAll(columnNameAndShardingValuesMap.get(key));
}
return valueSet;
}
}
Collection<String>
Использование остается прежним из-за поддержки здоровья нескольких осколков.ComplexKeysShardingValue
Использовать ключ сегмента в качестве атрибута сегментаkey
, значение ключа сегментаvalue
изmap
для хранения свойств ключа сегмента.
стратегия сегментирования выражений строк
стратегия разделения выражения строки (InlineShardingStrategy
), использовать в конфигурацииGroovy
выражение, обеспечивающее доступ к=
а такжеIN
поддержка операций сегментирования, он поддерживает только один ключ сегмента.
Стратегия сегментации строкового выражения подходит для простых алгоритмов сегментации без специальных алгоритмов сегментации, что избавляет от утомительной разработки кода и является самой простой из нескольких стратегий сегментации.
Его конфигурация довольно лаконична, эта стратегия сегментирования используетinline.algorithm-expression
Напишите выражения.
Например:ds-$->{order_id % 2}
выражать правоorder_id
Выполните расчет по модулю,$
Это подстановочный знак, используемый для принятия результата по модулю и, наконец, для вычисления подбиблиотеки.ds-0
··· ds-n
, что в целом относительно просто.
# 行表达式分片键
sharding.jdbc.config.sharding.tables.t_order.database-strategy.inline.sharding-column=order_id
# 表达式算法
sharding.jdbc.config.sharding.tables.t_order.database-strategy.inline.algorithm-expression=ds-$->{order_id % 2}
Стратегия разделения подсказок
Стратегия разделения подсказок (HintShardingStrategy
) немного отличается от приведенных выше стратегий сегментирования.Эта стратегия сегментирования не требует настройки ключей сегментов, и значения ключей сегментов больше не анализируются из SQL.Вместо этого информация о сегментах указывается извне, так что SQL может указать Executed в подбиблиотеках и подтаблицах.ShardingSphere
пройти черезHint
API реализует указанную операцию, которая фактически является правилом шардинга.tablerule
,databaserule
От централизованной конфигурации к индивидуальной конфигурации.
Например, если мы хотим, чтобы таблица заказовt_order
использоватьuser_id
Используйте ключ сегментирования для сегментирования базы данных и таблицы, ноt_order
нет в таблицеuser_id
В этом поле ключ сегмента или библиотеку сегментов можно вручную указать извне через Hint API.
Ниже мы приведем SQL без условия фрагментации, чтобы увидеть, как указать ключ фрагментации, чтобы направить его в указанную библиотечную таблицу.
SELECT * FROM t_order;
Использование стратегии сегментирования подсказки также необходимо настроить и внедрить.HintShardingAlgorithm
интерфейс и переопределениеdoSharding()
метод.
/**
* @author xinzhifu
* @description hit分表算法
* @date 2020/11/2 12:06
*/
public class MyTableHintShardingAlgorithm implements HintShardingAlgorithm<String> {
@Override
public Collection<String> doSharding(Collection<String> tableNames, HintShardingValue<String> hintShardingValue) {
Collection<String> result = new ArrayList<>();
for (String tableName : tableNames) {
for (String shardingValue : hintShardingValue.getValues()) {
if (tableName.endsWith(String.valueOf(Long.valueOf(shardingValue) % tableNames.size()))) {
result.add(tableName);
}
}
}
return result;
}
}
После настройки алгоритма реализуется только его часть, и его нужно передать перед вызовом SQL.HintManager
Укажите информацию о подбиблиотеке и подтаблице. Поскольку каждое добавляемое правило помещается вThreadLocal
внутри, поэтому сначала выполнитеclear()
Очистите последнее правило, иначе будет сообщено об ошибке;addDatabaseShardingValue
Установите ключевое значение ключа сегмента базы данных,addTableShardingValue
Задайте значение ключа сегмента таблицы сегментов.setMasterRouteOnly
Разделение чтения и записи заставляет главную библиотеку чтения избегать задержек, вызванных репликацией ведущий-ведомый.
// 清除掉上一次的规则,否则会报错
HintManager.clear();
// HintManager API 工具类实例
HintManager hintManager = HintManager.getInstance();
// 直接指定对应具体的数据库
hintManager.addDatabaseShardingValue("ds",0);
// 设置表的分片健
hintManager.addTableShardingValue("t_order" , 0);
hintManager.addTableShardingValue("t_order" , 1);
hintManager.addTableShardingValue("t_order" , 2);
// 在读写分离数据库中,Hint 可以强制读主库
hintManager.setMasterRouteOnly();
отладка отладки видит, что у нас естьt_order
Таблица задает значение ключа сегментирования таблицы сегментирования, которое можно использовать в пользовательском алгоритме.HintShardingValue
параметры успешно получены.
properties
Нет необходимости указывать ключ сегментирования в конфигурации в файле, достаточно пути к классу пользовательского алгоритма сегментирования Hint.
# Hint分片算法
spring.shardingsphere.sharding.tables.t_order.table-strategy.hint.algorithm-class-name=com.xiaofu.sharding.algorithm.tableAlgorithm.MyTableHintShardingAlgorithm
Далее функции Sharding-JDBC будут реализованы одна за другой, такие как распределенные транзакции, управление услугами и т. д. В следующей статье мы рассмотрим «Как настроить распределенные самовозрастающие идентификаторы первичных ключей для подбаз данных и Подтаблицы».
Адрес кейса на GitHub:GitHub.com/Программист-NDS…
Разобраны и розданы друзьям сотни различных технических электронных книг. Подпишитесь на официальный аккаунт, чтобы ответить【666] Самовывоз. Мы создали группу технического обмена с друзьями, чтобы обсуждать технологии и делиться технической информацией, стремясь вместе учиться и развиваться. Если вам интересно, присоединяйтесь к нам!