Partager via


Migration dynamique vers Azure Managed Instance pour Apache Cassandra en utilisant un proxy de double écriture

Si possible, nous vous recommandons d’utiliser la fonctionnalité native Apache Cassandra pour migrer des données de votre cluster existant vers Azure Managed Instance pour Apache Cassandra en configurant un cluster hybride. Cette capacité utilise le protocole gossip d’Apache Cassandra pour répliquer des données de votre centre de données source sur votre nouveau centre de données d’instance managée de façon directe.

Il peut y avoir certains scénarios où votre version de base de données source n’est pas compatible ou qu’une configuration de cluster hybride n’est pas possible. Ce tutoriel explique comment migrer des données vers Azure Managed Instance pour Apache Cassandra de façon dynamique en utilisant un proxy de double écriture et Apache Spark. Le proxy à double écriture est utilisé pour capturer les modifications en direct pendant que les données historiques sont copiées en bloc à l’aide d’Apache Spark. Les avantages de cette approche sont les suivants :

  • Modification minimale de l’application. Le proxy peut accepter des connexions depuis votre code d’application avec peu ou pas de modifications de configuration. Il route toutes les requêtes vers votre base de données source et route de manière asynchrone les écritures dans une cible secondaire.
  • Dépendance du protocole filaire du client. Étant donné que cette approche ne dépend pas des ressources principales ou des protocoles internes, elle peut être utilisée avec n’importe quel système Cassandra source ou cible qui implémente le protocole filaire Apache Cassandra.

L’approche proposée est illustrée dans l’image suivante.

Animation montrant la migration dynamique de données vers Azure Managed Instance pour Apache Cassandra.

Prérequis

Approvisionner un cluster Spark

Nous vous recommandons de sélectionner le runtime Azure Databricks version 7.5, qui prend en charge Spark 3.0.

Capture d’écran montrant la recherche de la version du runtime Azure Databricks.

Ajouter des dépendances Spark

Vous devez ajouter la bibliothèque du connecteur Cassandra Apache Spark à votre cluster pour vous connecter aux points de terminaison Apache Cassandra compatibles avec les protocoles de transmission. Dans votre cluster, sélectionnez Bibliothèques>Installer nouveau>Maven, puis ajoutez com.datastax.spark:spark-cassandra-connector-assembly_2.12:3.0.0 dans les coordonnées Maven.

Important

Si vous devez conserver le writetime Apache Cassandra de chaque ligne pendant la migration, nous vous recommandons d’utiliser cet exemple. Le fichier jar de dépendance dans cet exemple contient également le connecteur Spark. Installez donc cette version au lieu de l’assembly de connecteur.

Cet exemple est également utile si vous voulez valider une comparaison de lignes entre la source et la cible une fois le chargement des données historiques terminé. Consultez Exécuter le chargement des données historiques et valider la source et la cible.

Capture d’écran montrant la recherche de packages Maven dans Azure Databricks.

Sélectionnez Installer, puis redémarrez le cluster une fois l’installation terminée.

Remarque

Veillez à redémarrer le cluster Azure Databricks après l’installation de la bibliothèque du connecteur Cassandra.

Installer le proxy de double écriture

Pour des performances optimales pendant les écritures doubles, nous vous recommandons d’installer le proxy sur tous les nœuds de votre cluster Cassandra source.

#assuming you do not have git already installed
sudo apt-get install git 

#assuming you do not have maven already installed
sudo apt install maven

#clone repo for dual-write proxy
git clone https://github.com/Azure-Samples/cassandra-proxy.git

#change directory
cd cassandra-proxy

#compile the proxy
mvn package

Démarrer le proxy de double écriture

Nous vous recommandons d’installer le proxy sur tous les nœuds dans votre cluster Cassandra source. Au minimum, exécutez la commande suivante pour démarrer le proxy sur chaque nœud. Remplacez <target-server> par l’adresse IP ou de serveur de l’un des nœuds dans le cluster cible. Remplacez par <path to JKS file> le chemin d’accès à un fichier jks local, puis remplacez <keystore password> par le mot de passe correspondant.

java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar localhost <target-server> --proxy-jks-file <path to JKS file> --proxy-jks-password <keystore password>

Démarrer le proxy de cette façon suppose que les conditions suivantes sont réunies :

  • Les points de terminaison source et cible ont le même nom d’utilisateur et le même mot de passe.
  • Les points de terminaison source et cible implémentent SSL (Secure Sockets Layer).

Si vos points de terminaison source et cible ne peuvent pas répondre à ces critères, consultez les informations ci-dessous pour d’autres options de configuration.

Configuration du chiffrement SSL

Pour SSL, vous pouvez implémenter un magasin de clés existant, par exemple celui utilisé par votre cluster source ou créer un certificat auto-signé à l’aide keytoolde :

keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass password -validity 360 -keysize 2048

Vous pouvez aussi désactiver SSL pour les points de terminaison source ou cible s’ils n’implémentent pas SSL. Utilisez les indicateurs --disable-source-tls ou --disable-target-tls :

java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar localhost <target-server> \
  --source-port 9042 --target-port 10350 --proxy-jks-file <path to JKS file> \
  --proxy-jks-password <keystore password> --target-username <username> --target-password <password> \
  --disable-source-tls true  --disable-target-tls true 

Remarque

Assurez-vous que votre application cliente utilise le même magasin de clés et le même mot de passe que ceux utilisés pour le proxy double écriture lorsque vous générez des connexions SSL à la base de données qui utilisent le proxy.

Configurer les informations d’identification et le port

Par défaut, les informations d’identification sources sont transmises à partir de votre application cliente. Le proxy utilise les informations d’identification pour établir des connexions aux clusters source et cible. Comme mentionné plus haut, ce processus suppose que les informations d’identification de la source et de la cible sont identiques. Si nécessaire, vous pouvez spécifier un nom d’utilisateur et un mot de passe différents pour le point de terminaison Cassandra cible séparément lors du démarrage du proxy :

java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar localhost <target-server> \
  --proxy-jks-file <path to JKS file> --proxy-jks-password <keystore password> \
  --target-username <username> --target-password <password>

Les ports source et cible par défaut, lorsqu’ils ne sont pas spécifiés, sont 9042. Si le point de terminaison Cassandra cible ou source s’exécute sur un autre port, vous pouvez utiliser --source-port ou --target-port pour spécifier un numéro de port différent :

java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar localhost <target-server> \
  --source-port 9042 --target-port 10350 --proxy-jks-file <path to JKS file> \
  --proxy-jks-password <keystore password> --target-username <username> --target-password <password>

Déployer le proxy à distance

Il peut y avoir des circonstances dans lesquelles vous ne souhaitez pas installer le proxy sur les nœuds de cluster eux-mêmes. Vous souhaitez l’installer sur un ordinateur distinct. Dans ce scénario, spécifiez l’adresse IP de <source-server>:

java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar <source-server> <destination-server>

Avertissement

Vous pouvez exécuter le proxy à distance sur un ordinateur distinct plutôt que de l’exécuter sur tous les nœuds de votre cluster Apache Cassandra source. Si c’est le cas, nous vous recommandons de déployer le proxy sur le même nombre d’ordinateurs que vous avez des nœuds dans votre cluster. Configurez une substitution pour leurs adresses IP dans system.peer. Utilisez cette configuration dans le proxy. Si vous n’utilisez pas cette approche, cela peut affecter les performances pendant la migration dynamique, car le pilote client ne peut pas ouvrir de connexions à tous les nœuds du cluster.

Autoriser les modifications sans aucun code d’application

Par défaut, le proxy écoute sur le port 29042. Vous devez modifier le code de l’application pour qu’il pointe vers ce port. Vous pouvez également modifier le port sur lequel le proxy écoute. Vous pouvez utiliser cette approche si vous souhaitez éliminer les modifications de code au niveau de l’application en procédant comme suit :

  • Faire en sorte que le serveur Cassandra source s’exécute sur un port différent.
  • Faire en sorte que le proxy s’exécute sur le port Cassandra standard 9042.
java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar source-server destination-server --proxy-port 9042

Remarque

L’installation du proxy sur les nœuds de cluster ne nécessite pas de redémarrage des nœuds. Si vous avez de nombreux clients d’application et que vous préférez exécuter le proxy sur le port Cassandra standard 9042 pour éliminer les modifications de code au niveau de l’application, modifiez le port par défaut Apache Cassandra. Vous devez ensuite redémarrer les nœuds de votre cluster et configurer le port source pour qu’il corresponde au nouveau port que vous avez défini pour votre cluster Cassandra source.

Dans l’exemple suivant, nous modifions le cluster Cassandra source pour qu’il s’exécute sur le port 3074 et nous démarrons le cluster sur le port 9042 :

java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar source-server destination-server --proxy-port 9042 --source-port 3074

Forcer les protocoles

Le proxy dispose de fonctionnalités pour forcer les protocoles, ce qui peut être nécessaires si le point de terminaison source est plus avancé que la cible ou s’il n’est pas pris en charge. Dans ce cas, vous pouvez spécifier --protocol-version et --cql-version pour forcer le protocole à se conformer à la cible :

java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar source-server destination-server --protocol-version 4 --cql-version 3.11

Une fois le proxy double écriture exécuté, modifiez le port sur votre client d’application et redémarrez. Ou modifiez le port Cassandra et redémarrez le cluster si vous avez choisi cette approche. Le proxy commence à transférer des écritures dans le point de terminaison cible. Des informations sur la surveillance et les métriques dans l’outil proxy sont disponibles.

Effectuer le chargement des données d’historique

Pour charger les données, créez un notebook Scala dans votre compte Azure Databricks. Remplacez vos configurations Cassandra source et cible par les informations d’identification correspondantes, et remplacez les espaces de clés et les tables sources et cibles. Ajoutez des variables à l’exemple ci-dessous pour chaque table en fonction des besoins, puis lancez l’exécution. Une fois que votre application a commencé à envoyer des demandes au proxy de double écriture, vous êtes prêt à migrer les données d’historique.

import com.datastax.spark.connector._
import com.datastax.spark.connector.cql._
import org.apache.spark.SparkContext

// source cassandra configs
val sourceCassandra = Map( 
    "spark.cassandra.connection.host" -> "<Source Cassandra Host>",
    "spark.cassandra.connection.port" -> "9042",
    "spark.cassandra.auth.username" -> "<USERNAME>",
    "spark.cassandra.auth.password" -> "<PASSWORD>",
    "spark.cassandra.connection.ssl.enabled" -> "true",
    "keyspace" -> "<KEYSPACE>",
    "table" -> "<TABLE>"
)

//target cassandra configs
val targetCassandra = Map( 
    "spark.cassandra.connection.host" -> "<Source Cassandra Host>",
    "spark.cassandra.connection.port" -> "9042",
    "spark.cassandra.auth.username" -> "<USERNAME>",
    "spark.cassandra.auth.password" -> "<PASSWORD>",
    "spark.cassandra.connection.ssl.enabled" -> "true",
    "keyspace" -> "<KEYSPACE>",
    "table" -> "<TABLE>",
    //throughput related settings below - tweak these depending on data volumes. 
    "spark.cassandra.output.batch.size.rows"-> "1",
    "spark.cassandra.output.concurrent.writes" -> "1000",
    "spark.cassandra.connection.remoteConnectionsPerExecutor" -> "1",
    "spark.cassandra.concurrent.reads" -> "512",
    "spark.cassandra.output.batch.grouping.buffer.size" -> "1000",
    "spark.cassandra.connection.keep_alive_ms" -> "600000000"
)

//set timestamp to ensure it is before read job starts
val timestamp: Long = System.currentTimeMillis / 1000

//Read from source Cassandra
val DFfromSourceCassandra = sqlContext
  .read
  .format("org.apache.spark.sql.cassandra")
  .options(sourceCassandra)
  .load
  
//Write to target Cassandra
DFfromSourceCassandra
  .write
  .format("org.apache.spark.sql.cassandra")
  .options(targetCassandra)
  .option("writetime", timestamp)
  .mode(SaveMode.Append)
  .save

Remarque

Dans l’exemple Scala précédent, timestamp est défini sur l’heure actuelle avant de lire toutes les données de la table source. Ensuite writetime est défini sur cet horodatage antidaté. Cette approche garantit que les enregistrements écrits depuis le chargement des données d’historique sur le point de terminaison cible ne peuvent pas remplacer les mises à jour qui arrivent avec un horodatage ultérieur en provenance du proxy de double écriture pendant la lecture des données d’historique.

Important

Si pour une raison quelconque, vous devez conserver les horodatages exacts, il vous faut adopter une approche de la migration des données d’historique qui conserve les horodatages, comme dans cet exemple. Le fichier jar de dépendance dans l’exemple contient également le connecteur Spark. Vous n’avez donc pas besoin d’installer l’assembly de connecteur Spark mentionné dans les prérequis précédents. L’installation des deux dans votre cluster Spark provoque des conflits.

Vérifier la source et la cible

Une fois le chargement des données d’historique terminé, vos bases de données doivent être synchronisées et prêtes pour le basculement. Nous vous recommandons de vérifier que la source et la cible correspondent bien avant d’effectuer le basculement final.

Remarque

Si vous avez utilisé l’exemple de migration Cassandra mentionné dans les sections précédentes pour la conservation writetime, vous avez la possibilité de valider la migration en comparant les lignes dans la source et la cible en fonction de certaines tolérances.

Étape suivante