Livemigration von Daten aus Apache Cassandra in Azure Cosmos DB for Apache Cassandra mithilfe eines Proxys für duales Schreiben und von Apache Spark

Die API für Cassandra in Azure Cosmos DB hat sich aus einer Reihe unterschiedlicher Gründe zu einer guten Wahl für Unternehmensworkloads entwickelt, die in Apache Cassandra ausgeführt werden:

  • Kein Mehraufwand für Verwaltung und Überwachung: Beseitigt den Mehraufwand der Verwaltung und Überwachung von unzähligen Einstellungen für Betriebssystem, JVM und YAML-Dateien und deren Interaktionen.

  • Erhebliche Kosteneinsparungen: Sie können Kosten sparen mit Azure Cosmos DB, einschließlich der Kosten für virtuelle Computer, Bandbreite und alle anwendbaren Lizenzen. Außerdem entfällt die Verwaltung der Kosten für Rechenzentren, Server, SSD-Speicher, Netzwerk und Strom.

  • Möglichkeit der Verwendung von vorhandenem Code und Tools: Azure Cosmos DB bietet Kompatibilität auf Verbindungsprotokollebene mit vorhandenen SDKs und Tools. Durch diese Kompatibilität ist sichergestellt, dass Sie die vorhandene Codebasis mit Azure Cosmos DB for Apache Cassandra mit nur geringfügigen Änderungen verwenden können.

Azure Cosmos DB unterstützt nicht das systemeigene Apache-Cassandra-Gossip-Protokoll für die Replikation. Daher ist ein anderer Ansatz erforderlich, wenn keine Ausfallzeiten für die Migration erforderlich sind. In diesem Tutorial wird beschrieben, wie Sie Daten live mithilfe eines Proxys für duales Schreiben und von Apache Spark aus einem nativen Apache Cassandra-Cluster in Azure Cosmos DB for Apache Cassandra migrieren.

Die Vorgehensweise ist in der folgenden Abbildung dargestellt. Der Proxy für duales Schreiben stellt die fortlaufende Erfassung von Live-Änderungen sicher, während Apache Spark Verlaufsdaten als Massenvorgang kopiert. Damit der Proxy Verbindungen von Ihrem Anwendungscode akzeptiert, sind wenig bis keine Konfigurationsänderungen nötig. Er leitet alle Anforderungen an Ihre Quelldatenbank und Schreibvorgänge asynchron an die API für Cassandra weiter, während ein Massenkopiervorgang erfolgt.

Animation, die die Livemigration von Daten zu Azure Managed Instance for Apache Cassandra zeigt.

Voraussetzungen

Bereitstellen eines Spark-Clusters

Wir empfehlen Azure Databricks. Verwenden Sie eine Laufzeit, die Spark 3.0 oder höher unterstützt.

Wichtig

Sie müssen sicherstellen, dass Ihr Azure Databricks-Konto über Netzwerkkonnektivität mit Ihrem Apache Cassandra-Quellencluster verfügt. Dies erfordert möglicherweise VNet-Einfügen. Weitere Informationen finden Sie hier im Artikel.

Screenshot, der die Suche nach der Azure Databricks-Laufzeitversion zeigt.

Hinzufügen von Spark-Abhängigkeiten

Sie müssen dem Cluster die Apache Spark-Cassandra-Connectorbibliothek hinzufügen, um eine Verbindung mit nativen und Azure Cosmos DB-Cassandra-Endpunkten herzustellen. Wählen Sie in Ihrem Cluster Bibliotheken>Neue>Maveninstallieren und fügen Sie dann com.datastax.spark:spark-cassandra-connector-assembly_2.12:3.0.0 in Maven-Koordinaten hinzu.

Wichtig

Wenn Sie die Anforderung haben, Apache Cassandra writetime für jede Zeile während der Migration zu erhalten, empfehlen wir dieses Beispiel zu benutzen. Die in diesem Beispiel bereitgestellte JAR-Datei mit den Abhängigkeiten enthält auch den Spark-Connector. Sie sollten diesen anstelle der zuvor verwendeten Connector-Assembly installieren. Dieses Beispiel zeigt auch, wie der Zeilenvergleich zwischen Quelle und Ziel nach dem Laden der Verlaufsdaten überprüft wird. Weitere Informationen finden Sie unten in den Abschnitten Laden der Verlaufsdaten und Überprüfen der Quelle und des Ziels.

Screenshot, der zeigt, wie Maven-Pakete in Azure Databricks gesucht werden.

Wählen Sie Installieren aus, und starten Sie den Cluster nach Abschluss der Installation neu.

Hinweis

Stellen Sie sicher, dass Sie den Azure Databricks-Cluster neu starten, nachdem die Cassandra-Connectorbibliothek installiert wurde.

Installieren Sie den Proxy für duales Schreiben.

Für eine optimale Leistung bei dualen Schreibvorgängen wird empfohlen, den Proxy auf allen Knoten in Ihrem Cassandra-Quellcluster zu installieren.

#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

Starten des Proxys für duales Schreiben

Es wird empfohlen, den Proxy auf allen Knoten in Ihrem Cassandra-Quellcluster zu installieren. Führen Sie mindestens den folgenden Befehl aus, um den Proxy auf allen Knoten zu starten. Ersetzen Sie <target-server> durch eine IP- oder Serveradresse eines der Knoten im Zielcluster. Ersetzen Sie <path to JKS file> durch den Pfad zu einer lokalen .jks-Datei und <keystore password> durch das entsprechende Kennwort.

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>

Wenn Sie den Proxy auf diese Weise starten, muss Folgendes zutreffen:

  • Quell- und Zielendpunkte besitzen denselben Benutzernamen und dasselbe Kennwort.
  • Quell- und Zielendpunkte implementieren Secure Sockets Layer (SSL).

Wenn Ihre Quell- und Zielendpunkte diese Kriterien nicht erfüllen können, finden Sie nachfolgend weitere Konfigurationsoptionen.

Konfigurieren von SSL

Für SSL können Sie entweder einen vorhandenen Keystore implementieren (z. B. den von Ihrem Quellcluster verwendeten), oder Sie können mit keytool ein selbstsigniertes Zertifikat erstellen:

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

Wenn die Quell- oder Zielendpunkte SSL nicht implementieren, können Sie dieses auch deaktivieren. Verwenden Sie hierzu die Flags --disable-source-tls oder --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 

Hinweis

Stellen Sie sicher, dass Ihre Clientanwendung beim Erstellen von SSL-Verbindungen mit der Datenbank über den Proxy denselben Keystore und dasselbe Kennwort wie für den Proxy für duales Schreiben verwendet.

Konfigurieren der Anmeldeinformationen und des Ports

Standardmäßig werden die Anmeldeinformationen der Quelle von Ihrer Client-App übergeben. Der Proxy verwendet diese Anmeldeinformationen zum Herstellen einer Verbindung mit den Quell- und Zielclustern. Wie bereits erwähnt, wird bei diesem Prozess davon ausgegangen, dass die Quell- und Zielanmeldeinformationen identisch sind. Bei Bedarf können Sie einen anderen Benutzernamen und ein anderes Kennwort für den API für Cassandra-Zielendpunkt beim Starten des Proxys separat angeben:

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>

Werden die Quell- und Zielports nicht angegeben, lautet der Standardwert 9042. In diesem Fall wird die API für Cassandra an Port 10350 ausgeführt, sodass Sie mithilfe von --source-port oder --target-port die Portnummern angeben müssen:

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>

Remote-Bereitstellung des Proxymoduls

Möglicherweise möchten Sie den Proxy nicht auf den Clusterknoten selbst, sondern auf einem separaten Computer installieren. Geben Sie in diesem Fall die IP-Adresse von <source-server> an:

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

Warnung

Eine Remote-Installation und -Ausführung des Proxys auf einem separaten Computer (anstatt dessen Ausführung auf allen Knoten in Ihrem Apache Cassandra-Cluster) beeinträchtigt die Leistung während der Livemigration. Der Proxy ist zwar funktionsfähig, jedoch kann der Clienttreiber keine Verbindungen zu den Clusterknoten öffnen. Für die Verbindungsherstellung steht dem Treiber lediglich ein einziger Koordinatorknoten zur Verfügung, nämlich der Knoten, auf dem der Proxy installiert ist.

Keine Änderungen am Anwendungscode zulassen

Der Proxy lauscht standardmäßig an Port 29042. Der Anwendungscode muss so geändert werden, dass er auf diesen Port verweist. Sie können den Port, an dem der Proxy lauscht, jedoch auch ändern. Dies ist möglicherweise nötig, wenn Sie Codeänderungen auf Anwendungsebene vermeiden möchten, indem Sie:

  • den Cassandra-Quellservers auf einem anderen Port ausführen.
  • den Proxy auf dem Cassandra-Standardport 9042 ausführen.
java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar source-server destination-server --proxy-port 9042

Hinweis

Für die Installation des Proxys auf den Clusterknoten ist kein Neustart der Knoten erforderlich. Wenn Sie jedoch über viele Anwendungsclients verfügen und den Proxy auf dem Cassandra-Standardport 9042 ausführen, müssen Sie, um Codeänderungen auf Anwendungsebene zu vermeiden, den Apache Cassandra-Standardport ändern. Anschließend müssen Sie die Knoten in Ihrem Cluster neu starten und den Quellport als den neuen Port konfigurieren, den Sie für Ihren Cassandra-Quellcluster festgelegt haben.

Im folgenden Beispiel ändern wir den Cassandra-Quellcluster so, dass er auf dem Port 3074 ausgeführt wird, und wir starten den Cluster auf Port 9042:

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

Erzwingen von Protokollen

Der Proxy kann Protokolle erzwingen, die möglicherweise erforderlich sind, wenn der Quellendpunkt moderner ist als der Zielendpunkt, oder wenn der Quellendpunkt anderweitig nicht unterstützt wird. In diesem Fall können Sie --protocol-version und --cql-version festlegen, um die Übereinstimmung des Protokolls mit dem Zielendpunkt zu erzwingen:

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

Wenn der Proxy für duales Schreiben ausgeführt wird, müssen Sie den Port auf Ihrem Anwendungsclient ändern und neu starten. (Oder ändern Sie den Cassandra-Port und starten Sie den Cluster neu, wenn Sie diesen Ansatz gewählt haben.) Der Proxy beginnt dann mit der Weiterleitung von Schreibvorgängen an den Zielendpunkt. Weitere Informationen zur Überwachung und zu Metriken im Proxytool finden Sie hier.

Laden der Verlaufsdaten

Erstellen Sie zum Laden der Daten ein Scala-Notebook in Ihrem Azure Databricks-Konto. Ersetzen Sie Ihre Quell- und Zielkonfigurationen für Cassandra durch die entsprechenden Anmeldeinformationen sowie die Quell-und Zielkeyspaces und -tabellen. Fügen Sie im folgenden Beispiel nach Bedarf für jede Tabelle weitere Variablen hinzu, und führen Sie den Code anschließend aus. Nachdem Ihre Anwendung mit dem Senden von Anforderungen an den Proxy für duales Schreiben begonnen hat, können Sie die Verlaufsdaten migrieren.

Wichtig

Erhöhen Sie vor dem Migrieren der Daten den Containerdurchsatz auf den Betrag, der für eine schnelle Migration Ihrer Anwendung erforderlich ist. Das Skalieren des Durchsatzes vor dem Starten der Migration hilft Ihnen, Ihre Daten in kürzerer Zeit zu migrieren. Zum Schutz vor einer Ratenbegrenzung während des Ladens historischer Daten können Sie in der API für Cassandra serverseitige Wiederholungen (Server-Side Retries, SSR) aktivieren. Weitere Informationen und Anweisungen zum Aktivieren von SSR finden Sie hier.

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" -> "10350",
    "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

Hinweis

Im vorherigen Scala-Beispiel wird timestamp vor dem Lesen der Daten in der Quelltabelle auf den aktuellen Zeitpunkt festgelegt. Anschließend wird writetime auf diesen früheren Zeitstempel festgelegt. Dadurch wird sichergestellt, dass Datensätze, die aus den Verlaufsdaten auf den Zielendpunkt geschrieben werden, keine Updates mit einem späteren Zeitstempel aus dem Proxy für duales Schreiben überschreiben können, während die Verlaufsdaten gelesen werden.

Wichtig

Falls Sie jedoch die genauen Zeitstempel beibehalten müssen, sollten Sie die Verlaufsdaten auf eine Weise migrieren, bei der die Zeitstempel beibehalten werden, wie etwa in diesem Beispiel. Die in diesem Beispiel bereitgestellte JAR-Datei mit den Abhängigkeiten enthält auch den Spark-Connector. Sie brauchen also die in den vorangegangenen Voraussetzungen erwähnte Spark-Connector-Assembly nicht zu installieren. Die Installation sowohl des Spark-Connectors als auch der Spark-Connector-Assembly im gleichen Spark-Cluster führt zu Konflikten.

Überprüfen der Quelle und des Ziels

Nachdem das Laden der Verlaufsdaten abgeschlossen ist, sollten Ihre Datenbanken synchron und zur Übernahme bereit sein. Vor der endgültigen Übernahme wird jedoch eine Überprüfung der Quelle und des Ziels empfohlen, um sicherzustellen, dass beide übereinstimmen.

Hinweis

Wenn Sie das oben beschriebene Cassandra-Migrator-Beispiel verwendet haben, um writetime beizubehalten, finden Sie dort auch eine Methode zur Überprüfung der Migration durch Vergleich der Quell- und der Zielzeilen – vorbehaltlich gewisser Toleranzen.

Nächste Schritte