Tutoriel : Implémenter une base de données géo-distribuée (Azure SQL Database)

S’applique à Azure SQL Database

Configurez une base de données SQL Database et une application cliente pour le basculement vers une région distante, puis testez votre plan de basculement. Vous allez apprendre à effectuer les actions suivantes :

  • Créer un groupe de basculement
  • Exécuter une application Java pour interroger une base de données dans SQL Database
  • Test de basculement

Si vous ne disposez pas d’abonnement Azure, créez un compte gratuit avant de commencer.

Prérequis

Notes

Cet article utilise le module Azure Az PowerShell, qui est le module PowerShell recommandé pour interagir avec Azure. Pour démarrer avec le module Az PowerShell, consulter Installer Azure PowerShell. Pour savoir comment migrer vers le module Az PowerShell, consultez Migrer Azure PowerShell depuis AzureRM vers Az.

Important

Le module PowerShell Azure Resource Manager est toujours pris en charge par Azure SQL Database, mais tous les développements futurs sont destinés au module Az.Sql. Pour ces cmdlets, voir AzureRM.Sql. Les arguments des commandes dans le module Az sont sensiblement identiques à ceux des modules AzureRm.

Pour suivre le tutoriel, vérifiez que les éléments suivants sont installés :

Important

Veillez à configurer des règles de pare-feu pour pouvoir utiliser l’adresse IP publique de l’ordinateur sur lequel vous effectuez les étapes de ce tutoriel. Les règles de pare-feu au niveau de la base de données sont répliquées automatiquement sur le serveur secondaire.

Pour plus d’informations, consultez Créer une règle de pare-feu au niveau du serveur ou, pour déterminer l’adresse IP utilisée pour la règle de pare-feu au niveau du serveur pour votre ordinateur, consultez Créer une règle de pare-feu au niveau du serveur.

Créer un groupe de basculement

À l'aide d'Azure PowerShell, créez des groupes de basculement entre un serveur existant et un nouveau serveur situé dans une autre région. Ajoutez ensuite l’exemple de base de données au groupe de basculement.

Important

Cet exemple nécessite Azure PowerShell Az 1.0 ou ultérieur. Exécutez Get-Module -ListAvailable Az pour voir quelles versions sont installées. Si vous devez l’installer, consultez Installer le module Azure PowerShell.

Exécutez Connect-AzAccount pour vous connecter à Azure.

Pour créer un groupe de basculement, exécutez le script suivant :

$admin = "<adminName>"
$password = "<password>"
$resourceGroup = "<resourceGroupName>"
$location = "<resourceGroupLocation>"
$server = "<serverName>"
$database = "<databaseName>"
$drLocation = "<disasterRecoveryLocation>"
$drServer = "<disasterRecoveryServerName>"
$failoverGroup = "<globallyUniqueFailoverGroupName>"

# create a backup server in the failover region
New-AzSqlServer -ResourceGroupName $resourceGroup -ServerName $drServer `
    -Location $drLocation -SqlAdministratorCredentials $(New-Object -TypeName System.Management.Automation.PSCredential `
    -ArgumentList $admin, $(ConvertTo-SecureString -String $password -AsPlainText -Force))

# create a failover group between the servers
New-AzSqlDatabaseFailoverGroup –ResourceGroupName $resourceGroup -ServerName $server `
    -PartnerServerName $drServer –FailoverGroupName $failoverGroup –FailoverPolicy Automatic -GracePeriodWithDataLossHours 2

# add the database to the failover group
Get-AzSqlDatabase -ResourceGroupName $resourceGroup -ServerName $server -DatabaseName $database | `
    Add-AzSqlDatabaseToFailoverGroup -ResourceGroupName $resourceGroup -ServerName $server -FailoverGroupName $failoverGroup

Vous pouvez également changer les paramètres de géoréplication dans le portail Azure. Pour cela, sélectionnez votre base de données, puis Paramètres>Géoréplication.

Geo-replication settings

Exécuter l’exemple de projet

  1. Dans la console, créez un projet Maven avec la commande suivante :

    mvn archetype:generate "-DgroupId=com.sqldbsamples" "-DartifactId=SqlDbSample" "-DarchetypeArtifactId=maven-archetype-quickstart" "-Dversion=1.0.0"
    
  2. Tapez Y, puis appuyez sur Entrée.

  3. Passez au répertoire du nouveau projet.

    cd SqlDbSample
    
  4. À l’aide de votre éditeur habituel, ouvrez le fichier pom.xml dans le dossier de votre projet.

  5. Ajoutez la dépendance Pilote Microsoft JDBC pour SQL Server en ajoutant la section dependency suivante. La dépendance doit être collée dans la section dependencies plus grande.

    <dependency>
      <groupId>com.microsoft.sqlserver</groupId>
      <artifactId>mssql-jdbc</artifactId>
     <version>6.1.0.jre8</version>
    </dependency>
    
  6. Spécifiez la version de Java en ajoutant la section properties après la section dependencies :

    <properties>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
  7. Assurez la prise en charge des fichiers manifeste en ajoutant la section build après la section properties :

    <build>
      <plugins>
        <plugin>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-jar-plugin</artifactId>
          <version>3.0.0</version>
          <configuration>
            <archive>
              <manifest>
                <mainClass>com.sqldbsamples.App</mainClass>
              </manifest>
            </archive>
         </configuration>
        </plugin>
      </plugins>
    </build>
    
  8. Enregistrez et fermez le fichier pom.xml.

  9. Ouvrez le fichier App.java situé à l’emplacement ..\SqlDbSample\src\main\java\com\sqldbsamples et remplacez son contenu par le code suivant :

    package com.sqldbsamples;
    
    import java.sql.Connection;
    import java.sql.Statement;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.Timestamp;
    import java.sql.DriverManager;
    import java.util.Date;
    import java.util.concurrent.TimeUnit;
    
    public class App {
    
       private static final String FAILOVER_GROUP_NAME = "<your failover group name>";  // add failover group name
    
       private static final String DB_NAME = "<your database>";  // add database name
       private static final String USER = "<your admin>";  // add database user
       private static final String PASSWORD = "<your password>";  // add database password
    
       private static final String READ_WRITE_URL = String.format("jdbc:" +
          "sqlserver://%s.database.windows.net:1433;database=%s;user=%s;password=%s;encrypt=true;" +
          "hostNameInCertificate=*.database.windows.net;loginTimeout=30;",
          FAILOVER_GROUP_NAME, DB_NAME, USER, PASSWORD);
       private static final String READ_ONLY_URL = String.format("jdbc:" +
          "sqlserver://%s.secondary.database.windows.net:1433;database=%s;user=%s;password=%s;encrypt=true;" +
          "hostNameInCertificate=*.database.windows.net;loginTimeout=30;",
          FAILOVER_GROUP_NAME, DB_NAME, USER, PASSWORD);
    
       public static void main(String[] args) {
          System.out.println("#######################################");
          System.out.println("## GEO DISTRIBUTED DATABASE TUTORIAL ##");
          System.out.println("#######################################");
          System.out.println("");
    
          int highWaterMark = getHighWaterMarkId();
    
          try {
             for(int i = 1; i < 1000; i++) {
                 //  loop will run for about 1 hour
                 System.out.print(i + ": insert on primary " +
                    (insertData((highWaterMark + i)) ? "successful" : "failed"));
                 TimeUnit.SECONDS.sleep(1);
                 System.out.print(", read from secondary " +
                    (selectData((highWaterMark + i)) ? "successful" : "failed") + "\n");
                 TimeUnit.SECONDS.sleep(3);
             }
          } catch(Exception e) {
             e.printStackTrace();
       }
    }
    
    private static boolean insertData(int id) {
       // Insert data into the product table with a unique product name so we can find the product again
       String sql = "INSERT INTO SalesLT.Product " +
          "(Name, ProductNumber, Color, StandardCost, ListPrice, SellStartDate) VALUES (?,?,?,?,?,?);";
    
       try (Connection connection = DriverManager.getConnection(READ_WRITE_URL);
               PreparedStatement pstmt = connection.prepareStatement(sql)) {
          pstmt.setString(1, "BrandNewProduct" + id);
          pstmt.setInt(2, 200989 + id + 10000);
          pstmt.setString(3, "Blue");
          pstmt.setDouble(4, 75.00);
          pstmt.setDouble(5, 89.99);
          pstmt.setTimestamp(6, new Timestamp(new Date().getTime()));
          return (1 == pstmt.executeUpdate());
       } catch (Exception e) {
          return false;
       }
    }
    
    private static boolean selectData(int id) {
       // Query the data previously inserted into the primary database from the geo replicated database
       String sql = "SELECT Name, Color, ListPrice FROM SalesLT.Product WHERE Name = ?";
    
       try (Connection connection = DriverManager.getConnection(READ_ONLY_URL);
               PreparedStatement pstmt = connection.prepareStatement(sql)) {
          pstmt.setString(1, "BrandNewProduct" + id);
          try (ResultSet resultSet = pstmt.executeQuery()) {
             return resultSet.next();
          }
       } catch (Exception e) {
          return false;
       }
    }
    
    private static int getHighWaterMarkId() {
       // Query the high water mark id stored in the table to be able to make unique inserts
       String sql = "SELECT MAX(ProductId) FROM SalesLT.Product";
       int result = 1;
       try (Connection connection = DriverManager.getConnection(READ_WRITE_URL);
               Statement stmt = connection.createStatement();
               ResultSet resultSet = stmt.executeQuery(sql)) {
          if (resultSet.next()) {
              result =  resultSet.getInt(1);
             }
          } catch (Exception e) {
           e.printStackTrace();
          }
          return result;
       }
    }
    
  10. Enregistrez et fermez le fichier App.java.

  11. Dans la console de commandes, exécutez la commande suivante :

    mvn package
    
  12. Démarrez l’application. Celle-ci s’exécute pendant environ 1 heure jusqu’à ce que vous l’arrêtiez manuellement, ce qui vous donne le temps d’exécuter le test de basculement.

    mvn -q -e exec:java "-Dexec.mainClass=com.sqldbsamples.App"
    
    #######################################
    ## GEO DISTRIBUTED DATABASE TUTORIAL ##
    #######################################
    
    1. insert on primary successful, read from secondary successful
    2. insert on primary successful, read from secondary successful
    3. insert on primary successful, read from secondary successful
    ...
    

Test de basculement

Exécutez les scripts suivants pour simuler un basculement et observer les résultats de l’application. Notez l’échec de certaines insertions et sélections durant la migration de base de données.

Vous pouvez vérifier le rôle du serveur de reprise d’activité pendant le test avec la commande suivante :

(Get-AzSqlDatabaseFailoverGroup -FailoverGroupName $failoverGroup `
    -ResourceGroupName $resourceGroup -ServerName $drServer).ReplicationRole

Pour tester un basculement :

  1. Démarrer un basculement manuel du groupe de basculement :

    Switch-AzSqlDatabaseFailoverGroup -ResourceGroupName $resourceGroup `
     -ServerName $drServer -FailoverGroupName $failoverGroup
    
  2. Rétablir le groupe de basculement sur le serveur principal :

    Switch-AzSqlDatabaseFailoverGroup -ResourceGroupName $resourceGroup `
     -ServerName $server -FailoverGroupName $failoverGroup
    

Étapes suivantes

Révisez la liste de contrôle de haute disponibilité et récupération d’urgence.

Contenu connexe sur la base de données Azure SQL :