Condividi tramite


Aumentare il numero di istanze dei database con il gestore delle mappe partizioni

Si applica a:Database SQL di Azure

Per scalare facilmente i database sul Database SQL di Azure, usare un gestore di mappe di partizione. Il gestore delle mappe partizioni è un database speciale che gestisce le informazioni di mapping globale su tutte le partizioni (database) in un set di partizioni. I metadati consentono all'applicazione di connettersi al database corretto in base al valore della chiave di partizionamento orizzontale. Inoltre, ogni partizione nel set contiene le mappe che tengono traccia dei dati delle partizioni locali (i cosiddetti shardlet).

Diagramma di gestione delle mappe di shard.

Comprendere come sono costruite queste mappe è essenziale per la gestione delle mappe shard. Questa operazione viene eseguita usando la classe ShardMapManager (Java, .NET), disponibile in Compilazione di database cloud scalabili per gestire le mappe partizioni.

Mappe frammenti e mappature di frammenti

Per ogni frammento, è necessario selezionare il tipo di mappa di frammenti da creare. La scelta dipende dall'architettura del database:

  1. Singolo locatario per database
  2. Più tenant per database (due tipi):
    1. Mappatura elenco
    2. Mappatura dell'intervallo

Per un modello a tenant singolo, creare una mappa dei frammenti di tipo elenco. Il modello single-tenant assegna un database per tenant. Si tratta di un modello efficace per gli sviluppatori SaaS in quanto semplifica la gestione delle mappe partizioni.

Diagramma della mappatura dell'elenco.

Il modello multi-tenant assegna diversi tenant a un database singolo ed è possibile distribuire gruppi di tenant tra più database. Usare questo modello quando si prevedono esigenze di dati ridotte per ogni tenant. In questo modello, si assegnano una gamma di tenant a un database utilizzando la mappatura intervallo.

Diagramma della mappatura di intervallo.

In alternativa è possibile implementare un modello di database multi-tenant usando il mapping di tipo elenco per assegnare più tenant a un database singolo. Ad esempio, DB1 viene usato per archiviare le informazioni sugli ID tenant 1 e 5 e DB2 archivia i dati per i tenant 7 e 10.

Diagramma di tenant multipli in un singolo database.

Tipi supportati per le chiavi di partizionamento orizzontale

Elastic Scale supporta i seguenti tipi come chiavi di partizionamento orizzontale:

.RETE Giava
numero intero numero intero
lungo lungo
GUID UUID (Identificatore Unico Universale)
byte[] byte[]
data e ora Marca temporale
intervallo di tempo durata
datetimeoffset offsetdatetime

Mappe di frammenti di elenco e intervallo

Le mappe partizioni possono essere create usando elenchi di singoli valori di chiavi di partizionamento orizzontale oppure tramite intervalli di valori di chiavi di partizionamento orizzontale.

Mappe elenco frammenti

Le partizioni includono shardlet e il mapping degli shardlet alle partizioni viene gestito da una mappa partizioni. Una mappa partizioni di tipo elenco è un'associazione tra i singoli valori di chiave che identificano gli shardlet e i database che fungono da partizioni. I mapping di tipo elenco sono espliciti. È possibile eseguire il mapping di valori di chiave diversi allo stesso database. Il valore della chiave 1, ad esempio, è mappato al database A e i valori delle chiavi 3 e 6 sono entrambi mappati al database B.

Chiave Posizione dello shard
1 Database_A
3 Database_B
4 Database_C
6 Database_B
... ...

Mappa di partizioni a intervallo

In una mappa di intervallo, l'intervallo chiave è descritto da una coppia [Low Value, High Value), dove Low Value indica la chiave minima dell'intervallo e High Value è il primo valore superiore all'intervallo.

Ad esempio, [0, 100) include tutti i numeri interi superiori o uguali a 0 e inferiori a 100. Più intervalli possono puntare allo stesso database e sono supportati intervalli non contigui ,ad esempio [100.200) e [400.600) entrambi puntano a Database C nell'esempio seguente.

Chiave Posizione dello shard
[1, 50) Database_A
[50, 100) Database_B
[100, 200) Database_C
[400, 600) Database_C
... ...

Ognuna delle tabelle illustrate in precedenza è un esempio concettuale di un ShardMap oggetto . Ogni riga è un esempio semplificato di un singolo oggetto PointMapping (per la mappa delle partizioni dell'elenco) o oggetto RangeMapping (per la mappa delle partizioni di intervallo).

Gestore delle mappe di shard

Il gestore della mappa delle partizioni nella libreria del client è una raccolta di mappe delle partizioni. I dati gestiti da un'istanza ShardMapManager vengono mantenuti in tre posizioni:

  1. Mappa globale frammenti (GSM): si specifica un database da utilizzare come repository per tutte le sue mappe dei frammenti e i mapping corrispondenti. Vengono create automaticamente tabelle speciali e stored procedure per la gestione delle informazioni. Si tratta in genere di un database di piccole dimensioni e a cui si accede raramente ed è consigliabile non usarlo per altre esigenze dell'applicazione. Le tabelle si trovano in uno schema speciale denominato __ShardManagement.
  2. Local Shard Map (LSM): ogni database specificato come shard viene modificato per includere diverse piccole tabelle e speciali stored procedure, che contengono e gestiscono le informazioni della mappa shard specifiche per tale shard. Queste informazioni sono ridondanti rispetto a quelle nella mappa shard globale (GSM) e permettono all'applicazione di validare le informazioni sulla mappa shard memorizzate nella cache senza gravare sulla GSM; l'applicazione usa la mappa shard locale (LSM) per determinare se un mapping memorizzato nella cache è ancora valido. Anche le tabelle corrispondenti all'LSM in ogni partizione si trovano nello schema __ShardManagement.
  3. Cache delle applicazioni: ogni istanza dell'applicazione che accede a un ShardMapManager oggetto mantiene una cache in memoria locale dei relativi mapping. in cui vengono archiviate le informazioni di routing appena recuperate.

Costruire un oggetto ShardMapManager

Un ShardMapManager oggetto viene costruito usando un modello factory (Java, .NET). Il metodo ShardMapManagerFactory.GetSqlShardMapManager (Java, .NET) accetta delle credenziali (inclusi il nome del server e il nome del database che contiene il GSM) sotto forma di un ConnectionString e restituisce un'istanza di ShardMapManager.

Annotazioni

L'ShardMapManager dovrebbe essere istanziato solo una volta per ogni dominio dell'applicazione, all'interno del codice di inizializzazione per un'applicazione. La creazione di istanze aggiuntive di ShardMapManager nello stesso dominio app comporta un aumento della memoria e dell'utilizzo della CPU dell'applicazione. Un ShardMapManager può contenere un numero qualsiasi di mappe di shard. Anche se una singola mappa partizioni potrebbe essere sufficiente per molte applicazioni, in alcuni casi vengono usati set di database diversi per schemi diversi o per scopi univoci; in questi casi è possibile preferire più mappe partizioni.

In questo codice un'applicazione tenta di aprire un oggetto esistente ShardMapManager con il TryGetSqlShardMapManager (metodo Java, .NET . Se gli oggetti che rappresentano un ShardMapManager global (GSM) non esistono ancora all'interno del database, la libreria client li crea usando il CreateSqlShardMapManager metodo (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.
}

Per la versione .NET, è possibile usare PowerShell per creare un nuovo gestore delle mappe di partizioni.

Ottenere una mappa RangeShardMap o ListShardMap

Dopo la creazione di un gestore di mappe partizioni, è possibile ottenere RangeShardMap (Java, .NET) o ListShardMap (Java, .NET) con il metodo TryGetRangeShardMap (Java, .NET), TryGetListShardMap (Java, .NET) o 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;
}

Credenziali di amministrazione delle mappe partizioni

Le applicazioni che amministrano e modificano le mappe partizioni sono diverse da quelle che usano le mappe partizioni per il routing delle connessioni.

Per amministrare le mappe shard (aggiungere o modificare shard, mappe shard, mapping di shard e così via) è necessario istanziare il ShardMapManager utilizzando credenziali che dispongono di privilegi di lettura/scrittura sia per il database GSM che per ogni database che funge da shard. Le credenziali devono consentire operazioni di scrittura nelle tabelle sia nella Mappa Globale dei Frammenti (GSM) che nella Mappa Locale dei Frammenti (LSM) durante l'inserimento o la modifica delle informazioni sulla mappa, oltre a consentire la creazione di tabelle LSM nei nuovi frammenti.

Vedere Credenziali usate per accedere alla libreria client dei database elastici.

Impatto solo sui metadati

I metodi usati per popolare o modificare i ShardMapManager dati non modificano i dati utente archiviati nelle partizioni stesse. Ad esempio, i metodi come CreateShard, DeleteShard, UpdateMappinge così via influiscono solo sui metadati della mappa partizioni. Essi non rimuovono, aggiungono o modificano i dati utente contenuti nelle partizioni. Questi metodi sono stati invece progettati per l'uso insieme a operazioni separate eseguite per creare o rimuovere i database effettivi o per rimuovere righe da una partizione a un'altra, in modo da bilanciare nuovamente un ambiente partizionato Lo strumento di suddivisione-unione incluso negli strumenti di database elastici usa queste API insieme all'orchestrazione dello spostamento effettivo dei dati tra le partizioni. Vedere Spostamento di dati tra database cloud con scalabilità orizzontale.

Instradamento dipendente dai dati

Lo strumento di gestione delle mappe partizioni viene usato dalle applicazioni che richiedono connessioni a database per eseguire operazioni specifiche sui dati. Tali connessioni devono essere associate al database corretto. Questa procedura è nota come routing dipendente dai dati. Per queste applicazioni, instanziare un oggetto gestore della mappa shard dalla factory usando le credenziali con accesso di sola lettura al database GSM. Le singole richieste per connessioni successive forniscono le credenziali necessarie per la connessione al database partizioni appropriato.

Queste applicazioni (aperte con credenziali di sola lettura ShardMapManager) non possono apportare modifiche alle mappe o alle mappature. A questo scopo è possibile creare applicazioni specifiche per l'amministrazione o script di PowerShell che forniscono credenziali con privilegi elevati, come illustrato in precedenza. Vedere Credenziali usate per accedere alla libreria client dei database elastici.

Per altre informazioni, vedere Usare il routing dipendente dai dati per instradare una query a un database appropriato.

Modificare una mappa partizioni

È possibile modificare una mappa partizioni in molti modi diversi. Tutti i seguenti metodi modificano i metadati che descrivono le partizioni e i rispettivi mapping, ma non modificano fisicamente i dati nelle partizioni e non creano o eliminano i database effettivi. Alcune delle operazioni seguenti sulla mappa partizioni potrebbero dover essere coordinate con azioni amministrative che spostano fisicamente i dati o che aggiungono e rimuovono i database che fungono da partizioni.

Questi metodi interagiscono tra loro come i blocchi predefiniti disponibili per la modifica della distribuzione complessiva dei dati nell'ambiente di database partizionati.

  • Per aggiungere o rimuovere partizioni: usare CreateShard (Java, .NET) e DeleteShard (Java, .NET) della classe shardmap (Java, .NET).

    • Per permettere l'esecuzione di queste operazioni, è necessario che il server e il database che rappresentano la partizione di destinazione esistano già. Questi metodi non hanno alcun impatto sui database stessi. Influiscono solo sui metadati nella mappa partizioni.
  • Per creare o rimuovere punti o intervalli mappati alle partizioni: usare CreateRangeMapping (Java, .NET), DeleteMapping (Java, .NET) della classe RangeShardMapping (Java, .NET) e CreatePointMapping (Java, .NET) della classe ListShardMap (Java, .NET).

    È possibile mappare molti punti o intervalli diversi alla stessa partizione. Questi metodi influiscono solo sui metadati, non influiscono sui dati che potrebbero essere già presenti nelle partizioni. Se i dati devono essere rimossi dal database per essere coerenti con DeleteMapping le operazioni, è necessario eseguire queste operazioni separatamente, ma in combinazione con l'uso di questi metodi.

  • Per suddividere gli intervalli esistenti in due intervalli o unire intervalli adiacenti in uno: usare SplitMapping (Java, .NET) e MergeMappings (Java, .NET).

    Le operazioni di suddivisione e unione non modificano la partizione in cui vengono mappati i valori di chiave. Una suddivisione divide un intervallo esistente in due parti, ma entrambe rimangono mappate allo stesso shard. La fusione opera su due intervalli adiacenti che sono già mappati alla stessa partizione, coalizzandoli in un unico intervallo. Il movimento di punti o intervalli tra le partizioni deve essere coordinato utilizzando UpdateMapping insieme allo spostamento effettivo dei dati. È possibile usare il servizio di suddivisione/unione , incluso nello strumento dei database elastici, per coordinare le modifiche della mappa partizioni con lo spostamento dei dati, nei casi in cui lo spostamento è necessario.

  • Per eseguire nuovamente il mapping (o spostare) singoli punti o intervalli in partizioni diverse: usare UpdateMapping (Java, .NET).

    Poiché i dati potrebbero dover essere spostati da una partizione a un'altra per essere coerenti con UpdateMapping le operazioni, è necessario eseguire lo spostamento separatamente, ma in combinazione con l'uso di questi metodi.

  • Per portare i mapping online e offline: usare MarkMappingOffline (Java, .NET) e MarkMappingOnline (Java, .NET) per controllare lo stato online di un mapping.

    Alcune operazioni sulle mappature delle partizioni sono consentite solo quando una mappatura è in stato di offline, inclusi UpdateMapping e DeleteMapping. Quando un mapping è offline, una richiesta dipendente dai dati e basata su una chiave inclusa nel mapping restituisce un errore. Quando si porta offline per la prima volta un intervallo, inoltre, tutte le connessioni alla partizione interessata verranno terminate automaticamente per evitare risultati incoerenti o incompleti per le query dirette agli intervalli sottoposti a modifica.

I mapping sono oggetti non modificabili in .NET. Tutti i metodi precedenti che modificano i mapping invalidano anche tutti i riferimenti ad essi nel codice. Per semplificare l’esecuzione di sequenze di operazioni che modificano lo stato di un mapping, tutti i metodi che consentono di modificare un mapping restituiscono un nuovo riferimento di mapping, in modo che le operazioni possano essere concatenate. Ad esempio, per eliminare un mapping esistente in shardmap sm che contiene la chiave 25, è possibile eseguire le operazioni seguenti:

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

Aggiungere una partizione

Per una mappa partizioni già esistente, le applicazioni devono spesso aggiungere nuove partizioni per gestire i dati previsti dalle nuove chiavi o dai nuovi intervalli di chiavi. Ad esempio, un'applicazione suddivisa in base all'ID del tenant potrebbe dover effettuare il provisioning di un nuovo frammento per un nuovo tenant, oppure nel caso di dati suddivisi mensilmente, potrebbe essere necessario eseguire il provisioning di un nuovo frammento prima dell'inizio di ogni nuovo mese.

Se il nuovo intervallo di valori di chiave non è ancora incluso in un mapping esistente e non è necessario alcuno spostamento di dati, l'aggiunta della nuova partizione e l'associazione della nuova chiave o del nuovo intervallo a tale partizione sono semplici. Per informazioni dettagliate sull'aggiunta di nuove partizioni, vedere Aggiunta di una partizione tramite gli strumenti di database elastici.

Per gli scenari che richiedono lo spostamento di dati, tuttavia, il servizio di suddivisione-unione è necessario per l'orchestrazione dello spostamento di dati tra le partizioni insieme agli aggiornamenti necessari per la mappa partizioni. Per informazioni dettagliate sull'uso dello strumento di suddivisione-unione, vedere Spostamento di dati tra database cloud con scalabilità orizzontale

Non stai ancora usando gli strumenti di database elastici? vedere la Guida introduttiva. In caso di domande, usare la pagina Microsoft Q&A per il database SQL, mentre è possibile inserire le richieste di nuove funzionalità, aggiungere nuove idee o votare quelle esistenti nel forum relativo al feedback sul database SQL.