Как использовать промежуточное ПО базы данных для расширения кластера MySQL — руководство по использованию Kingshard
В предыдущей статье я рассказывал о дизайне Kingshard. Эта статья получила много внимания от заинтересованных читателей. Один из них спросил, могу ли я написать статью о том, как использовать Kingshard для создания расширяемого кластера MySQL.
У меня было свободное время, и я написал руководство по использованию Kingshard, в котором я объясню, как правильно использовать промежуточное программное обеспечение Kingshard на основе моего понимания MySQL Proxy.
1. Сценарии использования Kingshard
Многие интернет-компании всё ещё широко используют MySQL для хранения различных типов реляционных данных. По мере увеличения объёма данных и количества запросов разработчики сталкиваются с новыми проблемами:
Мы можем реализовать эти решения на стороне клиента, но это также сделает клиент более сложным и менее гибким. Как разработчик, специализирующийся на разработке баз данных, я разработал промежуточное ПО Kingshard на основе болевых точек разработки баз данных. Kingshard предлагает подходящие решения для вышеупомянутых пяти проблем. Ниже я подробно опишу основные функции Kingshard и продемонстрирую их.
2. Установка и запуск
(1). Настройка файла конфигурации
Вот пример файла конфигурации, который пользователи могут настроить в соответствии со своими потребностями:
# Адрес и порт Kingshard
addr : 0.0.0.0:9696
# Имя пользователя и пароль для подключения к Kingshard
user : kingshard
password : kingshard
# Порт веб-API Kingshard
web_addr : 0.0.0.0:9797
# Имя пользователя и пароль для вызова API
web_user : admin
web_password : admin
# Уровень журнала, [debug|info|warn|error], по умолчанию — error
log_level : debug
# Включить или отключить SQL-журнал, установить значение on; выключить SQL-журнал, установить значение off
log_sql : on
# Если установлено, выводить только SQL-журналы, выполнение которых занимает больше времени, чем slow_log_time (мс), в противном случае выводить все SQL-журналы
slow_log_time : 100
# Путь к файлу журнала, если не настроен, вывод будет направлен на терминал.
log_path : /Users/flike/log
# Файл чёрного списка SQL, все SQL в этом файле будут отклонены Kingshard
blacklist_sql_file: /Users/flike/blacklist
# Разрешить только IP-адресам в списке подключаться к Kingshard, если не настроено, подключение к IP-адресу Kingshard не ограничено.
allow_ips: 127.0.0.1
# Набор символов, используемый Kingshard, если набор символов не установлен, Kingshard использует utf8 в качестве набора символов по умолчанию
proxy_charset: utf8mb4
# Один узел узла представляет собой фрагмент данных MySQL кластера, включая один главный и несколько подчинённых (можно не настраивать подчинённые)
nodes :
-
# Имя узла
name : node1
# Максимальное количество свободных соединений в пуле соединений, то есть максимальное количество соединений, которое Kingshard может установить с базой данных MySQL
max_conns_limit : 16
# Пользователь, подключающийся к базе данных MySQL в Kingshard, имя пользователя и пароль главного и подчиненного сервера должны совпадать
user : kingshard
password : kingshard
# Главный сервер
master : 127.0.0.1:3306
# Подчинённый сервер, можно не настраивать
slave : 192.168.0.12@2,192.168.0.13@3
# Если Kingshard не может подключиться к MySQL в течение 300 секунд, Kingshard отключит этот MySQL
down_after_noalive : 300
-
name : node2
max_conns_limit : 16
user : kingshard
password : kingshard
master : 192.168.59.103:3307
slave :
down_after_noalive: 100
# Правила разделения таблиц
schema :
# Узел, на который распределяются неразделённые таблицы
default: node1
shard:
-
# База данных, используемая для разделения таблиц
db : kingshard
# Имя таблицы
table: test_shard_hash
# Ключ разделения таблицы
key: id
# Узел распределения таблицы
nodes: [node1,node2]
# Тип разделения таблицы
type: hash
# Распределение дочерних таблиц, указывающее, что node1 имеет 4 дочерние таблицы,
node2 имеет 4 дочерние таблицы.
locations: [4,4]
-
# База данных, используемая для разделения таблиц
db : kingshard
# Имя таблицы
table: test_shard_range
# Ключ разделения таблицы
key: id
# Тип разделения таблицы
type: range
# Разделение узлов таблицы
nodes: [node1, node2]
# Количество дочерних таблиц на узел, указывающее, что на node1 имеется 4 дочерних таблицы, а на node2 — 4 дочерних таблицы.
locations: [4,4]
# Представляет максимальное количество записей в каждой дочерней таблице, то есть каждая дочерняя таблица может содержать не более 10 000 записей. То есть дочерняя таблица 1 соответствует диапазону идентификаторов [0,10000), дочерняя таблица 2 соответствует диапазону [10000,20000)....
table_row_limit: 10000
Здесь я хотел бы подчеркнуть правила разделения таблиц:
* Kingshard поддерживает два типа правил разделения таблиц: hash и range.
* Дочерние таблицы, участвующие в разделении таблиц Kingshard, должны быть созданы вручную в соответствующих базах данных, формат: `table_name_%4d`, то есть индекс дочерней таблицы состоит из 4 цифр. Например: `table_name_0000,table_name_0102`.
* Все операции с неразделёнными таблицами SQL будут отправляться на узел по умолчанию.
**(2). Установка и запуск Kingshard**
1. Установите среду выполнения Go (версия Go 1.3 или выше), подробные шаги см. в Google.
2. git clone https://github.com/flike/kingshard.git src/github.com/flike/kingshard
3. cd src/github.com/flike/kingshard
4. source ./dev.sh
5. make
6. Настройте файл конфигурации
7. Запустите Kingshard. ./bin/kingshard -config=etc/ks.yaml
**Примечание: Kingshard будет реагировать на сигналы SIGINT, SIGTERM и SIGQUIT, плавно завершая работу. Рекомендуется избегать отправки этих сигналов на машине, где работает Kingshard, чтобы избежать ненормального завершения работы Kingshard! Рекомендуется использовать инструмент supervisor для запуска Kingshard в фоновом режиме.**
**3. Разделение таблиц между узлами**
Поскольку у меня есть только две базы данных MySQL, я создал два узла, оба из которых имеют только одну главную роль MySQL, а конкретная топология выглядит следующим образом:

### 3.1. Демонстрация операций разделения таблиц **Разделение таблиц на шарды: типы и создание подтаблиц**
Существуют два типа разделения таблиц на шарды — hash и range. В этом тексте рассматривается только разделение по типу hash. Разделение по типу range работает аналогично, поэтому не будет рассматриваться здесь.
На узлах node1 и node2 создаются по 4 подтаблицы. Приведён пример создания подтаблицы test_shard_hash_0000 на узле node1:
```CREATE TABLE `test_shard_hash_0000` (
`id` bigint(64) unsigned NOT NULL,
`str` varchar(256) DEFAULT NULL,
`f` double DEFAULT NULL,
`e` enum('test1','test2') DEFAULT NULL,
`u` tinyint(3) unsigned DEFAULT NULL,
`i` tinyint(4) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8```
**Вставка и запрос данных в разделённые таблицы**
Выполняются SQL-запросы для вставки данных в таблицу test_shard_hash. Запросы выполняются на разных узлах, и данные распределяются по соответствующим подтаблицам.
Для обеспечения согласованности данных рекомендуется использовать транзакции при обновлении данных на нескольких узлах.
Соответствующие записи в журнале SQL:
```2015/09/02 18:48:24 - INFO - 127.0.0.1:55003->192.168.59.103:3307:insert into test_shard_hash_0007(id, str, f, e, u, i) values (15, 'flike', 3.14, 'test2', 2, 3)
2015/09/02 18:49:05 - INFO - 127.0.0.1:55003->192.168.59.103:3307:insert into test_shard_hash_0007(id, str, f, e, u, i) values (7, 'chen', 2.1, 'test1', 32, 3)```
Можно видеть, что первые две строки были отправлены на узел node2, а вторые две — на узел node1.
Затем выполняется запрос SELECT для просмотра данных. Запрос поддерживает запросы к нескольким узлам.
Запись в журнале SQL:
```mysql> select * from test_shard_hash where id < 18;
+----+--------+------+-------+------+------+
| id | str | f | e | u | i |
+----+--------+------+-------+------+------+
| 17 | github | 2.5 | test1 | 32 | 3 |
| 7 | chen | 2.1 | test1 | 32 | 3 |
| 15 | flike | 3.14 | test2 | 2 | 3 |
+----+--------+------+-------+------+------+
3 rows in set (0.02 sec)```
Поскольку используется разделение по типу hash, для запросов диапазона необходимо запрашивать каждую подтаблицу отдельно. Соответствующие записи в журнале SQL:
```2015/09/02 18:55:01 - INFO - 127.0.0.1:55003->127.0.0.1:3306:select * from test_shard_hash_0000 where id < 18
2015/09/02 18:55:01 - INFO - 127.0.0.1:55003->127.0.0.1:3306:select * from test_shard_hash_0001 where id < 18
2015/05/02 18:55:01 - INFO - 127.0.0.1:55003->127.0.0.1:3306:select * from test_shard_hash_0002 where id < 18
2015/09/02 18:55:01 - INFO - 127.0.0.1:55003->127.0.0.1:3306:select * from test_shard_hash_0003 where id < 18```
Запрос SELECT с условием равенства также выполняется на каждом узле отдельно.
Записи в журнале SQL:
```mysql> select * from test_shard_hash where id = 18;
+----+-----------+------+-------+------+------+
| id | str | f | e | u | i |
+----+-----------+------+-------+------+------+
| 18 | kingshard | 7.3 | test1 | 32 | 3 |
+----+-----------+------+-------+------+------+
1 row in set (0.00 sec)```
```2015/09/02 18:59:37 - INFO - 127.0.0.1:55003->127.0.0.1:3306:select * from test_shard_hash_0002 where id = 18``` **3.5. Порядок через узлы**
Kingshard поддерживает порядок через узлы. Kingshard сначала отправляет соответствующий SQL на нужный узел, а затем сортирует результаты в памяти, тем самым реализуя операцию порядка через select. Пример:
mysql> select * from test_shard_hash where id > 1 order by id; +----+-----------+------+-------+------+------+ | id | str | f | e | u | i | +----+-----------+------+-------+------+------+ | 7 | chen | 2.1 | test1 | 123 | 3 | | 15 | flike | 3.14 | test2 | 123 | 3 | | 17 | github | 2.5 | test1 | 32 | 23 | | 18 | kingshard | 7.3 | test1 | 32 | 23 | +----+-----------+------+-------+------+------+ 4 rows in set (0.02 sec)
Соответствующий журнал SQL:
2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select * from test_shard_hash_0000 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select * from test_shard_hash_0001 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select * from test_shard_hash_0002 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->127.0.0.1:3306:select * from test_shard_hash_0003 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select * from test_shard_hash_0004 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select * from test_shard_hash_0005 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select * from test_shard_hash_0006 where id > 1 order by id asc 2015/09/03 14:54:11 - INFO - 127.0.0.1:55768->192.168.59.103:3307:select * from test_shard_hash_0007 where id > 1 order by id asc
**4. Транзакции одного узла**
Kingshard позволяет выполнять транзакции на одном узле, что означает, что одна транзакция не может охватывать несколько узлов. Если возникает ситуация с несколькими узлами, kingshard вернёт ошибку клиенту. Можно использовать разные дочерние таблицы на одном и том же узле. Пример:
mysql> begin; Query OK, 0 rows affected (0.00 sec)
mysql> insert into test_shard_hash(id,str,f,e,u,i) values(23,'proxy',9.2,'test1',12,3); Query OK, 1 row affected (0.00 sec)
mysql> commit; Query OK, 0 rows affected (0.01 sec)
Если в одной транзакции появляется запрос, который должен выполняться на другом узле, kingshard возвращает ошибку:
#SQL-запрос выполняется на узле 2 mysql> insert into test_shard_hash(id,str,f,e,u,i) values(31,'proxy',9.2,'test1',12,3); Query OK, 1 row affected (0.01 sec) #SQL-запрос должен быть выполнен на узле 1 mysql> insert into test_shard_hash(id,str,f,e,u,i) values(40,'proxy',9.2,'test1',12,3); ERROR 1105 (HY000): transaction in multi node
**6. Управление Kingshard**
Интерфейс управления Kingshard в настоящее время реализован в виде командной строки. В будущем планируется преобразовать его в веб-интерфейс. Конкретные команды управления можно найти в документации.
Формат команд управления можно разделить на две категории:
* `admin server(opt,k,v)`
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )