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).

Gestione delle mappe shard

Comprendere come sono costruite queste mappe è essenziale per la gestione delle mappe shard. A questo scopo si usa la classe ShardMapManager (Java, .NET), disponibile nella libreria client dei database elastici.

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.

Mappatura 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.

Mappatura dell'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.

Molteplici tenant su un singolo database

Tipi supportati per le chiavi di partizionamento orizzontale

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

.NET Java
integer integer
lungo lungo
GUID uuid
byte[] byte[]
data e ora timestamp
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. Si noti che più intervalli possono fare riferimento allo stesso database e che sono supportati intervalli non contigui. Ad esempio, [100,200) e [400,600) fanno entrambi riferimento al 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 precedenti è un esempio concettuale di un oggetto ShardMap . Ogni riga costituisce un esempio semplificato di un singolo oggetto PointMapping (per la mappa partizioni di tipo elenco) o RangeMapping (per la mappa partizioni di tipo 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 di ShardMapManager sono conservati 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. Le tabelle corrispondenti all'LSM su ciascun frammento si trovano anche nello schema __ShardManagement.
  3. Cache dell'applicazione: ogni istanza di applicazione che accede a un oggetto ShardMapManager gestisce una cache in memoria locale dei rispettivi mapping, in cui vengono archiviate le informazioni di routing appena recuperate.

Creazione di un oggetto ShardMapManager

Un oggetto ShardMapManager viene creato utilizzando un pattern factory (Java, .NET). Il metodo ShardMapManagerFactory.GetSqlShardMapManager (Java, .NET) accetta credenziali, inclusi il nome del server e il nome del database contenente la mappa globale partizioni, sotto forma di oggetto ConnectionString, e restituisce un'istanza di un oggetto ShardMapManager.

Nota: è sufficiente creare una sola istanza di ShardMapManager per ogni dominio app, nel codice di inizializzazione dell'applicazione. La creazione di istanze aggiuntive di ShardMapManager nello stesso dominio comporta un aumento dell'utilizzo della memoria e della CPU dell'applicazione. Un oggetto ShardMapManager può contenere un numero qualsiasi di mappe di shard. Anche se è possibile che una singola mappa partizioni sia sufficiente per molte applicazioni, in alcune situazioni vengono usati diversi set di database per schemi diversi o per finalità specifiche. In questi casi è preferibile usare più mappe partizioni.

Nel codice seguente un'applicazione prova ad aprire un oggetto ShardMapManager esistente con il metodo TryGetSqlShardMapManager (Java, .NET. Se gli oggetti che rappresentano un oggetto ShardMapManager globale non esistono ancora nel database, vengono creati dalla libreria client con il metodo 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.
}

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 di shard (aggiungere o modificare shard, mappe di shard, mapping di shard, ecc.) è necessario istanziare lo ShardMapManager utilizzando credenziali con privilegi di lettura/scrittura sia sul database GSM che su 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 dati di ShardMapManager non influiscono sui dati utente archiviati nelle partizioni stesse. Ad esempio, i metodi come CreateShard, DeleteShard, UpdateMapping e così via interessano solo i 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 (il servizio di suddivisione-unione incluso negli strumenti dei database elastici usa queste API, oltre a orchestrare lo spostamento effettivo dei dati tra le partizioni). Vedere Dimensionare con lo strumento di suddivisione-unione del database elastico.

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.

Si noti che queste applicazioni, che usano l'oggetto ShardMapManager aperto con credenziali di sola lettura, non possono apportare modifiche alle mappe o ai mapping. 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 Routing dipendente dai dati.

Modifica di una mappa dei frammenti

È 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. Potrebbe essere necessario coordinare alcune operazioni sulla mappa partizioni descritte di seguito con le 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) e 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 sui dati eventualmente già presenti nelle partizioni. Se è necessario rimuovere dati dal database per assicurare la coerenza con le operazioni di tipo DeleteMapping, eseguire queste operazioni separatamente, ma contemporaneamente all'uso di questi metodi.

  • Per dividere in due gli intervalli esistenti o unire intervalli adiacenti in un unico intervallo: usare SplitMapping (Java, .NET) e MergeMappings (Java, .NET).

    Si noti che le operazioni di suddivisione e unione non modificano la partizione a cui sono 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. Lo spostamento di punti o degli stessi intervalli tra le partizioni deve essere coordinato tramite l'uso di 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 di nuovo il mapping di singoli punti o intervalli o spostare punti o intervalli in partizioni diverse usare UpdateMapping (Java, .NET).

    Poiché potrebbe essere necessario spostare i dati da una partizione a un'altra per mantenere la coerenza con le operazioni di tipo UpdateMapping, occorre eseguire separatamente lo spostamento, ma contemporaneamente all'uso di questi metodi.

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

    Alcune operazioni sui mapping di partizioni, incluse le operazioni UpdateMapping e DeleteMapping, sono consentite solo se lo stato del mapping è offline. 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)));

Aggiunta di 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, è possibile che un'applicazione partizionata dall'ID tenant debba eseguire il provisioning di una nuova partizione per un nuovo tenant, oppure è possibile che i dati partizionati ogni mese richiedano il provisioning di una nuova partizione 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 nuova partizione.

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 Panoramica dello strumento di suddivisione-unione

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.