Настройка высокой доступности Apache ShardingSphere с помощью MySQL
Узнайте, как и почему ShardingSphere может обеспечить высокую доступность базы данных на примере MySQL.
Пользователи имеют множество возможностей для настройки и расширения решений высокой доступности (HA) ShardingSphere. Наша команда реализовала два плана обеспечения высокой доступности: решение высокой доступности MySQL на основе MGR и решение высокой доступности базы данных openGauss, предоставленное некоторыми участниками сообщества. Принципы обоих решений одинаковы.
Ниже показано, как и почему ShardingSphere может обеспечить высокую доступность базы данных на примере MySQL:
(Чжао Цзиньчао, CC BY-SA 4.0)
Предварительное условие
ShardingSphere проверяет, готова ли базовая кластерная среда MySQL, выполняя следующий оператор SQL. ShardingSphere не может быть запущена, если какой-либо из тестов не пройден.
Проверьте, установлен ли MGR:
SELECT * FROM information_schema.PLUGINS WHERE PLUGIN_NAME='group_replication'
Просмотрите номер участника группы MGR. Базовый кластер MGR должен состоять как минимум из трех узлов:
SELECT count(*) FROM performance_schema.replication_group_members
Проверьте, соответствует ли имя группы кластера MGR имени в конфигурации. Имя группы является маркером группы MGR, и каждая группа кластера MGR имеет только одно имя группы:
SELECT * FROM performance_schema.global_variables WHERE VARIABLE_NAME='group_replication_group_name'
Проверьте, установлен ли текущий MGR в качестве единственного основного режима. В настоящее время ShardingSphere не поддерживает сценарии двойной или множественной записи. Он поддерживает только режим одиночной записи:
SELECT * FROM performance_schema.global_variables WHERE VARIABLE_NAME='group_replication_single_primary_mode'
Опросите все хосты узлов, порты и состояния в кластере группы MGR, чтобы проверить правильность настроенного источника данных:
SELECT MEMBER_HOST, MEMBER_PORT, MEMBER_STATE FROM performance_schema.replication_group_members
Динамическое обнаружение первичной базы данных
ShardingSphere находит URL-адрес основной базы данных в соответствии с командой SQL запроса главной базы данных, предоставленной MySQL:
private String findPrimaryDataSourceURL(final Map<String, DataSource> dataSourceMap) {
String result = "";
String sql = "SELECT MEMBER_HOST, MEMBER_PORT FROM performance_schema.replication_group_members WHERE MEMBER_ID = "
+ "(SELECT VARIABLE_VALUE FROM performance_schema.global_status WHERE VARIABLE_NAME = 'group_replication_primary_member')";
for (DataSource each : dataSourceMap.values()) {
try (Connection connection = each.getConnection();
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery(sql)) {
if (resultSet.next()) {
return String.format("%s:%s", resultSet.getString("MEMBER_HOST"), resultSet.getString("MEMBER_PORT"));
}
} catch (final SQLException ex) {
log.error("An exception occurred while find primary data source url", ex);
}
}
return result;
}
Сравните URL-адреса основной базы данных, указанные выше, один за другим с настроенными URL-адресами dataSources
. Сопоставленный источник данных — это основная база данных. Он будет обновлен до текущей памяти ShardingSphere и сохранен в центре реестра, через который он будет распространен на другие вычислительные узлы в кластере.
(Чжао Цзиньчао, CC BY-SA 4.0)
Динамическое обнаружение базы данных-получателя
В ShardingSphere существует два типа состояний вторичной базы данных: включить и отключить. Состояние базы данных-получателя будет синхронизировано с памятью ShardingSphere, чтобы обеспечить правильную маршрутизацию трафика чтения.
Получите все узлы в группе MGR:
SELECT MEMBER_HOST, MEMBER_PORT, MEMBER_STATE FROM performance_schema.replication_group_members
Отключите базы данных-получатели:
private void determineDisabledDataSource(final String schemaName, final Map<String, DataSource> activeDataSourceMap,
final List<String> memberDataSourceURLs, final Map<String, String> dataSourceURLs) {
for (Entry<String, DataSource> entry : activeDataSourceMap.entrySet()) {
boolean disable = true;
String url = null;
try (Connection connection = entry.getValue().getConnection()) {
url = connection.getMetaData().getURL();
for (String each : memberDataSourceURLs) {
if (null != url && url.contains(each)) {
disable = false;
break;
}
}
} catch (final SQLException ex) {
log.error("An exception occurred while find data source urls", ex);
}
if (disable) {
ShardingSphereEventBus.getInstance().post(new DataSourceDisabledEvent(schemaName, entry.getKey(), true));
} else if (!url.isEmpty()) {
dataSourceURLs.put(entry.getKey(), url);
}
}
}
Отключение базы данных-получателя зависит от настроенного источника данных и всех узлов в группе MGR.
ShardingSphere может проверить одну за другой, может ли настроенный источник данных правильно получить Connection
, а также проверить, содержит ли URL-адрес источника данных узлы группы MGR.
Если Соединение
невозможно получить или проверка не удалась, ShardingSphere отключит источник данных с помощью триггера события и синхронизирует его с центром реестра.
Включите базы данных-получатели:
private void determineEnabledDataSource(final Map<String, DataSource> dataSourceMap, final String schemaName,
final List<String> memberDataSourceURLs, final Map<String, String> dataSourceURLs) {
for (String each : memberDataSourceURLs) {
boolean enable = true;
for (Entry<String, String> entry : dataSourceURLs.entrySet()) {
if (entry.getValue().contains(each)) {
enable = false;
break;
}
}
if (!enable) {
continue;
}
for (Entry<String, DataSource> entry : dataSourceMap.entrySet()) {
String url;
try (Connection connection = entry.getValue().getConnection()) {
url = connection.getMetaData().getURL();
if (null != url && url.contains(each)) {
ShardingSphereEventBus.getInstance().post(new DataSourceDisabledEvent(schemaName, entry.getKey(), false));
break;
}
} catch (final SQLException ex) {
log.error("An exception occurred while find enable data source urls", ex);
}
}
}
}
После того как поврежденная база данных-получатель будет восстановлена и добавлена в группу MGR, будет проверена конфигурация, чтобы определить, используется ли восстановленный источник данных. Если да, триггер события сообщит ShardingSphere, что источник данных необходимо включить.
Механизм сердцебиения
В модуль HA введен механизм Heartbeat, обеспечивающий синхронизацию первичного и вторичного состояний в режиме реального времени.
Благодаря интеграции подпроекта ShardingSphere ElasticJob вышеуказанные процессы выполняются платформой планировщика ElasticJob в форме задания при инициализации модуля высокой доступности, что обеспечивает разделение разработки функций и планирования заданий.
Даже если разработчикам необходимо расширить функцию высокой доступности, им не нужно заботиться о том, как создаются и управляются рабочие места:
private void initHeartBeatJobs(final String schemaName, final Map<String, DataSource> dataSourceMap) {
Optional<ModeScheduleContext> modeScheduleContext = ModeScheduleContextFactory.getInstance().get();
if (modeScheduleContext.isPresent()) {
for (Entry<String, DatabaseDiscoveryDataSourceRule> entry : dataSourceRules.entrySet()) {
Map<String, DataSource> dataSources = dataSourceMap.entrySet().stream().filter(dataSource -> !entry.getValue().getDisabledDataSourceNames().contains(dataSource.getKey()))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
CronJob job = new CronJob(entry.getValue().getDatabaseDiscoveryType().getType() + "-" + entry.getValue().getGroupName(),
each -> new HeartbeatJob(schemaName, dataSources, entry.getValue().getGroupName(), entry.getValue().getDatabaseDiscoveryType(), entry.getValue().getDisabledDataSourceNames())
.execute(null), entry.getValue().getHeartbeatProps().getProperty("keep-alive-cron"));
modeScheduleContext.get().startCronJob(job);
}
}
}
Заворачивать
На данный момент функция высокой доступности Apache ShardingSphere доказала свою применимость для решений высокой доступности MySQL и openGauss. В дальнейшем он будет интегрировать больше продуктов MySQL HA и поддерживать больше решений для обеспечения высокой доступности баз данных.
Как всегда, если вам интересно, вы можете присоединиться к нам и внести свой вклад в проект Apache ShardingSphere.
Ссылки на проект с открытым исходным кодом Apache ShardingSphere:
- ШардингСфера GitHub
- ШардингСфера Твиттер
- ShardingSphere Slack
- Рекомендации для авторов