Direktmigrering till Azure Managed Instance för Apache Cassandra med hjälp av en proxy med dubbel skrivning

Om möjligt rekommenderar vi att du använder den inbyggda Apache Cassandra-funktionen för att migrera data från ditt befintliga kluster till Azure Managed Instance för Apache Cassandra genom att konfigurera ett hybridkluster. Den här funktionen använder Apache Cassandras skvallerprotokoll för att replikera data från ditt källdatacenter till ditt nya hanterade instansdatacenter på ett sömlöst sätt. Det kan dock finnas vissa scenarier där din källdatabasversion inte är kompatibel, eller så är det inte möjligt att konfigurera ett hybridkluster.

I den här självstudien beskrivs hur du migrerar data till Azure Managed Instance för Apache Cassandra live med hjälp av en proxy med dubbla skrivningar och Apache Spark. Proxyn med dubbel skrivning används för att samla in liveändringar, medan historiska data kopieras i grupp med hjälp av Apache Spark. Fördelarna med den här metoden är:

  • Minimala programändringar. Proxyn kan acceptera anslutningar från programkoden med få eller inga konfigurationsändringar. Den dirigerar alla begäranden till källdatabasen och dirigerar skrivningar asynkront till ett sekundärt mål.
  • Klient trådprotokoll beroende. Eftersom den här metoden inte är beroende av backend-resurser eller interna protokoll kan den användas med alla Cassandra-käll- eller målsystem som implementerar Apache Cassandra-trådprotokollet.

Följande bild illustrerar metoden.

Animering som visar direktmigrering av data till Azure Managed Instance för Apache Cassandra.

Förutsättningar

Etablera ett Spark-kluster

Vi rekommenderar att Azure Databricks version 7.5, som stöder Spark 3.0.

Skärmbild som visar hur du Azure Databricks körningsversionen.

Lägga till Spark-beroenden

Du måste lägga till biblioteket Apache Spark Cassandra Connector i klustret för att ansluta till alla trådprotokollkompatibla Apache Cassandra-slutpunkter. I klustret väljer du Bibliotek Installera > ny > Maven och lägger sedan till com.datastax.spark:spark-cassandra-connector-assembly_2.12:3.0.0 i Maven-koordinater.

Viktigt

Om du har ett krav på att bevara Apache Cassandra writetime för varje rad under migreringen rekommenderar vi att du använder det här exemplet. Beroende-jar-filen i det här exemplet innehåller även Spark-anslutningsappen, så du bör installera det här i stället för anslutningssammansättningen ovan. Det här exemplet är också användbart om du vill utföra en radjämförelseverifiering mellan källa och mål när den historiska databelastningen har slutförts. Mer information finnsi avsnitten "körhistorisk databelastning" och"verifierakällan och målet" nedan.

Skärmbild som visar sökning efter Maven-paket i Azure Databricks.

Välj Installera och starta sedan om klustret när installationen är klar.

Anteckning

Se till att starta om Azure Databricks när Cassandra Connector-biblioteket har installerats.

Installera proxyn med dubbel skrivning

För optimala prestanda vid dubbla skrivningar rekommenderar vi att du installerar proxyn på alla noder i Cassandra-källklustret.

#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

Starta proxyn med dubbel skrivning

Vi rekommenderar att du installerar proxyn på alla noder i Cassandra-källklustret. Kör minst följande kommando för att starta proxyn på varje nod. Ersätt <target-server> med en IP- eller serveradress från en av noderna i målklustret. Ersätt <path to JKS file> med sökvägen till en lokal .jks-fil och <keystore password> ersätt med motsvarande lösenord.

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>

När proxyn startas på det här sättet förutsätts att följande är sant:

  • Käll- och målslutpunkter har samma användarnamn och lösenord.
  • Käll- och målslutpunkter implementerar Secure Sockets Layer (SSL).

Om dina käll- och målslutpunkter inte kan uppfylla dessa kriterier kan du läsa vidare för ytterligare konfigurationsalternativ.

Konfigurera SSL

För SSL kan du antingen implementera ett befintligt nyckellager (till exempel det som källklustret använder) eller skapa ett själv signerat certifikat med hjälp av keytool :

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

Du kan också inaktivera SSL för käll- eller målslutpunkter om de inte implementerar SSL. Använd --disable-source-tls --disable-target-tls flaggorna eller :

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 

Anteckning

Kontrollera att klientprogrammet använder samma nyckellager och lösenord som de som används för proxyn med dubbel skrivning när du skapar SSL-anslutningar till databasen via proxyn.

Konfigurera autentiseringsuppgifter och port

Som standard skickas autentiseringsuppgifterna för källan via din klientapp. Proxyn använder autentiseringsuppgifterna för att skapa anslutningar till käll- och målkluster. Som tidigare nämnts förutsätter den här processen att käll- och målautentiseringsuppgifterna är desamma. Om det behövs kan du ange ett annat användarnamn och lösenord för Cassandra-målslutpunkten separat när du startar proxyn:

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>

Standardportarna för källa och mål är 9042 när de inte anges. Om antingen målet eller Cassandra-källslutpunkten körs på en annan port kan du använda --source-port eller för att ange ett annat --target-port portnummer:

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>

Distribuera proxyn via fjärrinstallation

Det kan finnas omständigheter då du inte vill installera proxyn på själva klusternoderna och du föredrar att installera den på en separat dator. I det scenariot måste du ange IP-adressen för <source-server> :

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

Varning

Om du fjärrinstallerar och kör proxyn på en separat dator (i stället för att köra den på alla noder i Apache Cassandra-källklustret) påverkas prestandan medan direktmigrering sker. Även om det fungerar som det ska kan klientdrivrutinen inte öppna anslutningar till alla noder i klustret och förlitar sig på den enda samordnande noden (där proxyn är installerad) för att skapa anslutningar.

Tillåt noll ändringar i programkoden

Som standard lyssnar proxyn på port 29042. Programkoden måste ändras så att den pekar på den här porten. Du kan dock ändra den port som proxyn lyssnar på. Du kan göra detta om du vill eliminera kodändringar på programnivå genom att:

  • Att Cassandra-källservern körs på en annan port.
  • Låt proxyn köras på Cassandra-standardporten 9042.
java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar source-server destination-server --proxy-port 9042

Anteckning

Installation av proxyn på klusternoder kräver inte omstart av noderna. Men om du har många programklienter och föredrar att proxyn körs på Cassandra-standardporten 9042 för att eliminera eventuella kodändringar på programnivå, måste du ändra Apache Cassandra-standardporten. Sedan måste du starta om noderna i klustret och konfigurera källporten så att den är den nya porten som du definierade för Cassandra-källklustret.

I följande exempel ändrar vi Cassandra-källklustret så att det körs på port 3074, och vi startar klustret på port 9042:

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

Tvinga protokoll

Proxyn har funktioner för att tvinga protokoll, vilket kan vara nödvändigt om källslutpunkten är mer avancerad än målet eller på annat sätt inte stöds. I så fall kan du ange --protocol-version och för att tvinga protokollet att följa --cql-version målet:

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

När proxyn med dubbel skrivning körs måste du ändra porten på programklienten och starta om. (Eller ändra Cassandra-porten och starta om klustret om du har valt den metoden.) Proxyn börjar sedan vidarebefordra skrivningar till målslutpunkten. Du kan lära dig mer om övervakning och mått som är tillgängliga i proxyverktyget.

Köra den historiska databelastningen

Om du vill läsa in data skapar du en Scala-notebook-Azure Databricks konto. Ersätt dina Cassandra-käll- och målkonfigurationer med motsvarande autentiseringsuppgifter och ersätt käll- och målnyckelutrymmena och tabellerna. Lägg till fler variabler för varje tabell efter behov i följande exempel och kör sedan. När programmet börjar skicka begäranden till proxyn med dubbla skrivningar är du redo att migrera historiska data.

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

Anteckning

I föregående Scala-exempel ser du att är inställt på aktuell tid innan du läser timestamp alla data i källtabellen. Sedan ställs writetime den här tidsstämpeln för bakåt i tiden in. Detta säkerställer att poster som skrivs från den historiska databelastningen till målslutpunkten inte kan skriva över uppdateringar som kommer med en senare tidsstämpel från proxyn med dubbelskrivning medan historiska data läses.

Viktigt

Om du behöver bevara exakta tidsstämplar av någon anledning bör du använda en historisk datamigreringsmetod som bevarar tidsstämplar, till exempel det här exemplet. Beroende-jar-filen i exemplet innehåller även Spark-anslutningsappen, så du behöver inte installera Spark-anslutningssammansättningen som nämns i de tidigare förutsättningarna – om båda är installerade i Spark-klustret orsakar det konflikter.

Verifiera källan och målet

När den historiska databelastningen är klar bör dina databaser vara synkroniserade och redo för en direkt övergång. Vi rekommenderar dock att du verifierar källan och målet för att säkerställa att de matchar innan du slutligen går över.

Anteckning

Om du använde cassandra-urval som nämns ovan för att bevara inkluderar detta möjligheten att verifiera migreringen genom att jämföra rader i källan och målet baserat på writetime vissa toleranser.

Nästa steg