Поделиться через


Горизонтальное увеличение масштаба баз данных с использованием диспетчера карты сегментов

Применимо к: База данных SQL Azure

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

Управление картой шардов

Для управления картами сегментов важно понимать их структуру. Для этого используется класс ShardMapManager (Java, .NET), входящий в клиентскую библиотеку эластичной базы данных. Он позволяет управлять картами сегментов.

Карты шардов и сопоставления шардов

Для каждого сегмента следует выбрать тип создаваемой карты сегментов. Этот выбор зависит от архитектуры базы данных.

  1. По одному клиенту для каждой базы данных.
  2. Несколько тенантов в базе данных (два типа):
    1. Сопоставление по спискам
    2. Сопоставление по диапазонам

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

Сопоставление по спискам

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

Сопоставление по диапазонам

Вы также можете реализовать многопользовательскую модель базы данных с помощью отображения по списку, чтобы назначить нескольких арендаторов индивидуальной базе данных. Например, база данных DB1 используется для хранения информации о клиенте 1 и 5, а DB2 хранит данные о клиенте 7 и 10.

Несколько арендаторов в одной базе данных

Поддерживаемые типы для ключей сегментирования

Эластичное масштабирование поддерживает такие типы ключей сегментирования:

.NET Java
целое число целое число
длинный длинный
guid универсальный уникальный идентификатор (UUID)
byte[] byte[]
дата и время метка времени
период времени длительность
datetimeoffset offsetdatetime

Списочные и диапазонные карты шардов

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

Список карт шардирования

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

Ключ Расположение шарда
1 БазаДанных_А
3 БазаДанных_Б
4 БазаДанных_C
6 БазаДанных_Б
... ...

Карты шардов диапазонов

В картах сегментов по диапазонам диапазон ключей описывается парой [нижнее значение, верхнее значение), где нижнее значение — минимальный ключ в диапазоне, а верхнее значение — первое значение, превышающее диапазон.

Например [0, 100) включает все целые числа, которые больше или равны 0 и меньше 100. Обратите внимание, что несколько диапазонов могут указывать на одну и ту же базу данных, а также поддерживаются перекрытия диапазонов (например, в текущем примере оба диапазона [100,200) и [400,600) указывают на базы данных C).

Ключ Расположение сегмента
[1,50) БазаДанных_А
[50,100) БазаДанных_Б
[100,200) База Данных_C
[400,600) Database_C
... ...

Каждая из приведенных выше таблиц является концептуальным примером объекта ShardMap . Каждая строка представляет упрощенный пример отдельного PointMapping (для карты списка сегментов) или RangeMapping (для карты диапазона сегментов) объекта.

Диспетчер карты сегментов

В клиентской библиотеке менеджер карты сегментов представляет собой коллекцию карт сегментов. Данные, контролируемые объектом ShardMapManager , хранятся в трех местах.

  1. Глобальная карта сегментов (GSM): вы указываете базу данных для хранения всех карт сегментов и сопоставлений. Для управления этой информацией автоматически создаются специальные таблицы и хранимые процедуры. Обычно это база данных небольшая и с простым доступом, и её не рекомендуется использовать для других прикладных задач. Таблицы расположены в специальной схеме с именем __ShardManagement.
  2. Локальная карта сегментов (LSM): в каждую указанную вами в качестве сегмента базу данных будут добавлены несколько небольших таблиц и специальных хранимых процедур, которые содержат информацию о карте сегментов, относящуюся к этому сегменту, и управляют этой информацией. Эта информация является избыточной для данных в GSM и позволяет приложению проверять кэшированную информацию о карте сегментов без нагрузки на GSM; с помощью LSM приложение определяет, является ли кэшированное сопоставление все еще действительным. Таблицы, соответствующие LSM на каждом сегменте, также находятся в схеме __ShardManagement.
  3. Кэш приложения: каждый экземпляр приложения, у которого есть доступ к объекту ShardMapManager, поддерживает локальный кэш своих сопоставлений в памяти. Он хранит недавно извлеченную информацию о маршрутизации.

Создание объекта ShardMapManager

Объект ShardMapManager создается с помощью шаблона проектирования фабрика (Java, .NET). Метод ShardMapManagerFactory.GetSqlShardMapManager (Java, .NET) принимает учетные данные (включая имя сервера и имя базы данных, содержащей GSM) в формате ConnectionString и возвращает экземпляр ShardMapManager.

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

В этом коде приложение пытается открыть существующий экземпляр ShardMapManager с помощью метода TryGetSqlShardMapManager (Java, .NET). Если в базе данных отсутствуют глобальные объекты ShardMapManager, представляющие GSM, клиентская библиотека создаст их с помощью метода CreateSqlShardMapManager (Java, .NET).

// Try to get a reference to the Shard Map Manager in the shardMapManager database.
// If it doesn't already exist, then create it.
ShardMapManager shardMapManager = null;
boolean shardMapManagerExists = ShardMapManagerFactory.tryGetSqlShardMapManager(shardMapManagerConnectionString,ShardMapManagerLoadPolicy.Lazy, refShardMapManager);
shardMapManager = refShardMapManager.argValue;

if (shardMapManagerExists) {
    ConsoleUtils.writeInfo("Shard Map %s already exists", shardMapManager);
}
else {
    // The Shard Map Manager does not exist, so create it
    shardMapManager = ShardMapManagerFactory.createSqlShardMapManager(shardMapManagerConnectionString);
    ConsoleUtils.writeInfo("Created Shard Map %s", shardMapManager);
}
// Try to get a reference to the Shard Map Manager via the Shard Map Manager database.  
// If it doesn't already exist, then create it.
ShardMapManager shardMapManager;
bool shardMapManagerExists = ShardMapManagerFactory.TryGetSqlShardMapManager(
                                        connectionString,
                                        ShardMapManagerLoadPolicy.Lazy,
                                        out shardMapManager);

if (shardMapManagerExists)
{
    Console.WriteLine("Shard Map Manager already exists");
}
else
{
    // Create the Shard Map Manager.
    ShardMapManagerFactory.CreateSqlShardMapManager(connectionString);
    Console.WriteLine("Created SqlShardMapManager");

    shardMapManager = ShardMapManagerFactory.GetSqlShardMapManager(
            connectionString,
            ShardMapManagerLoadPolicy.Lazy);

// The connectionString contains server name, database name, and admin credentials for privileges on both the GSM and the shards themselves.
}

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

Получить RangeShardMap или ListShardMap

Создав диспетчер карты сегментов, вы можете получить объекты RangeShardMap (Java, .NET) или ListShardMap (Java, .NET) с помощью методов TryGetRangeShardMap (Java, .NET), TryGetListShardMap (Java, .NET) или GetShardMap (Java, .NET).

// Creates a new Range Shard Map with the specified name, or gets the Range Shard Map if it already exists.
static <T> RangeShardMap<T> createOrGetRangeShardMap(ShardMapManager shardMapManager,
            String shardMapName,
            ShardKeyType keyType) {
    // Try to get a reference to the Shard Map.
    ReferenceObjectHelper<RangeShardMap<T>> refRangeShardMap = new ReferenceObjectHelper<>(null);
    boolean isGetSuccess = shardMapManager.tryGetRangeShardMap(shardMapName, keyType, refRangeShardMap);
    RangeShardMap<T> shardMap = refRangeShardMap.argValue;

    if (isGetSuccess && shardMap != null) {
        ConsoleUtils.writeInfo("Shard Map %1$s already exists", shardMap.getName());
    }
    else {
        // The Shard Map does not exist, so create it
        try {
            shardMap = shardMapManager.createRangeShardMap(shardMapName, keyType);
        }
        catch (Exception e) {
            e.printStackTrace();
        }
        ConsoleUtils.writeInfo("Created Shard Map %1$s", shardMap.getName());
    }

    return shardMap;
}
// Creates a new Range Shard Map with the specified name, or gets the Range Shard Map if it already exists.
public static RangeShardMap<T> CreateOrGetRangeShardMap<T>(ShardMapManager shardMapManager, string shardMapName)
{
    // Try to get a reference to the Shard Map.
    RangeShardMap<T> shardMap;
    bool shardMapExists = shardMapManager.TryGetRangeShardMap(shardMapName, out shardMap);

    if (shardMapExists)
    {
        ConsoleUtils.WriteInfo("Shard Map {0} already exists", shardMap.Name);
    }
    else
    {
        // The Shard Map does not exist, so create it
        shardMap = shardMapManager.CreateRangeShardMap<T>(shardMapName);
        ConsoleUtils.WriteInfo("Created Shard Map {0}", shardMap.Name);
    }

    return shardMap;
}

Учетные данные для администрирования карты сегментов

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

Для администрирования карт сегментов (добавления или изменения сегментов, карт сегментов, сопоставлений сегментов и т. д.) необходимо создать экземпляр ShardMapManager с использованием учетных данных, для которых предусмотрены права на чтение и запись в базе GSM и в каждой базе данных, выступающей в качестве сегмента. Учетные данные должны давать право записи в таблицы в GSM и LSM при вводе или изменения информации карт сегментов, а также право создавать таблицы LSM в новых сегментах.

См. статью Учетные данные для доступа к клиентской библиотеке эластичной базы данных.

Воздействует только на метаданные

Методы, используемые для заполнения и изменения данных ShardMapManager , не воздействуют на данные пользователя, хранящиеся в самих сегментах. Например, такие методы, как CreateShard, DeleteShard, UpdateMapping и другие, влияют только на метаданные карты сегментов. Они не удаляют, не добавляют и не изменяют пользовательские данные, содержащиеся в сегментах. На самом деле, эти методы предназначены для использования с отдельными операциями, с помощью которых вы создаете и удаляете фактические базы данных, либо перемещаете строки между сегментами для выравнивания сегментированной среды. (Инструмент разбиения и объединения, входящий в состав инструментов эластичных баз данных, использует эти API-интерфейсы и управляет фактическим перемещением данных между шардов.) См. Масштабирование с использованием инструмента разбиения и объединения эластичной базы данных.

Маршрутизация, зависящая от данных

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

Обратите внимание, что эти приложения (использующие ShardMapManager в режиме только для чтения) не могут вносить изменения в карты и сопоставления. Для этого создайте специальные административные приложения или сценарии PowerShell, которые будут передавать учетные данные с более высокими правами доступа, как об этом говорилось ранее. См. статью Учетные данные для доступа к клиентской библиотеке эластичной базы данных.

Дополнительные сведения см. в статье Маршрутизация, зависящая от данных.

Изменение карты сегментов

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

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

  • Для добавления или удаления сегментов используйте CreateShard (Java, .NET) и DeleteShard (Java, .NET) из класса Shardmap (Java, .NET).

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

  • Для создания или удаления точек или диапазонов, сопоставленных с сегментами, используйте CreateRangeMapping (Java, .NET), DeleteMapping (Java, .NET) из класса RangeShardMapping (Java, .NET) и CreatePointMapping (Java, .NET) из класса ListShardMap (Java, .NET).

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

  • Чтобы разбить существующие диапазоны на два или объединить смежные диапазоны в один, используйте методы SplitMapping (Java, .NET) и MergeMappings (Java, .NET).

    Обратите внимание, что операции разбиения и слияния не изменяют сегмент, с которым сопоставляются ключевые значения. Функция разбиения разделяет существующий диапазон на две части, но оставляет их обе привязанными к одному сегменту. Функция объединения соединяет два соседних диапазона, привязанных к одному сегменту, в один целый диапазон. Перемещение точек или самих диапазонов между сегментами необходимо координировать с помощью UpdateMapping в сочетании с фактическим перемещением данных. Используйте службу Разбиения и Слияния, входящую в состав инструментов для работы с эластичными базами данных, чтобы согласовать изменения в карте шардов с перемещением данных, если это необходимо.

  • Для повторного сопоставления (или перемещения) отдельных точек или диапазонов в другие сегменты используйте метод UpdateMapping (Java, .NET).

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

  • Для перевода сопоставлений в сетевой и автономный режим используйте методы MarkMappingOffline (Java, .NET) и MarkMappingOnline (Java, .NET) для управления сетевым состоянием сопоставления.

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

Сопоставления в .NET являются неизменяемыми объектами. Все описанные выше методы, изменяющие сопоставление, также аннулируют все ссылки на них в коде. Чтобы упростить выполнение последовательностей операций, которые изменяют состояние сопоставления, все методы, изменяющие сопоставление, возвращают новую ссылку на сопоставление, чтобы операции могли быть связаны. Например, для удаления существующего сопоставления в sm shardmap, содержащего ключ 25, можно выполнить следующее:

    sm.DeleteMapping(sm.MarkMappingOffline(sm.GetMappingForKey(25)));

Добавление сегмента

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

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

Однако для случая, когда требуется перемещение данных, необходимо использовать инструмент разбиения и объединения для выполнения перемещения данных между сегментами в сочетании с необходимым обновлением карты сегментов. Сведения об использовании средств разбиения и слияния см. в статье Обзор разбиения и слияния

Еще не используете средства эластичных баз данных? Ознакомьтесь с нашим руководством по началу работы. Возникшие вопросы вы можете задать нам на странице вопросов Microsoft Q&A по Базе данных SQL. Что касается запросов новых функций, вы можете поделиться новыми идеями или проголосовать за существующие на форуме отзывов по Базе данных SQL.