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

Där det är 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 datacenter för hanterad instans på ett sömlöst sätt. Det kan dock finnas scenarier där källdatabasversionen inte är kompatibel eller om en hybridklusterkonfiguration annars inte är möjlig.

Den här självstudien beskriver hur du migrerar data till Azure Managed Instance för Apache Cassandra live med hjälp av en dubbelskrivningsproxy och Apache Spark. Proxyn med dubbel skrivning används för att samla in liveändringar, medan historiska data kopieras massvis med 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 asynkront skrivningar till ett sekundärt mål.
  • Beroende av klienttrådsprotokoll. Eftersom den här metoden inte är beroende av serverdelsresurser 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 du väljer Azure Databricks runtime version 7.5, som stöder Spark 3.0.

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

Lägga till Spark-beroenden

Du måste lägga till Apache Spark Cassandra Connector-biblioteket 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 i det här exemplet innehåller också Spark-anslutningsappen, så du bör installera detta i stället för anslutningssammansättningen ovan. Det här exemplet är också användbart om du vill utföra en verifiering av radjämförelse mellan källa och mål när den historiska datainläsningen har slutförts. Se avsnitten "kör den historiska datainläsningen" och "verifiera källan och målet" nedan för mer information.

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-klustret 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 ersätt <keystore password> 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>

Om du startar proxyn på det här sättet förutsätter vi att följande är sant:

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

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 nyckelarkiv (till exempel det som källklustret använder) eller skapa ett självsignerat certifikat med hjälp keytoolav :

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 flaggorna --disable-source-tls eller --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 

Anteckning

Kontrollera att klientprogrammet använder samma nyckelarkiv 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 källautentiseringsuppgifterna från klientappen. Proxyn använder autentiseringsuppgifterna för att upprätta 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, när de inte anges, är 9042. Om antingen målet eller Cassandra-källslutpunkten körs på en annan port kan du använda --source-port eller --target-port ange ett annat 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>

Fjärrdistribuering av proxyn

Det kan finnas omständigheter där 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 <source-server>för :

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

Varning

Om du föredrar att fjärrköra proxyn på en separat dator (i stället för att köra den på alla noder i apache Cassandra-källklustret) rekommenderar vi att du distribuerar proxyn till samma antal datorer som du har noder i klustret och konfigurerar en ersättning för deras IP-adresser i system.peers med hjälp av konfigurationen i proxyn som anges här. Om du inte gör det kan det påverka prestanda när direktmigreringen sker eftersom klientdrivrutinen inte kan öppna anslutningar till alla noder i klustret.

Tillåt noll programkodändringar

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.
  • Att proxyn körs 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 standardporten för Apache Cassandra. Sedan måste du starta om noderna i klustret och konfigurera källporten så att den är den nya port som du har definierat för ditt Cassandra-källkluster.

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

Framtvinga protokoll

Proxyn har funktioner för att framtvinga 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 --cql-version tvinga protokollet att uppfylla 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 har körts 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ör den historiska datainläsningen

Om du vill läsa in data skapar du en Scala-anteckningsbok i ditt Azure Databricks-konto. Ersätt dina cassandra-käll- och målkonfigurationer med motsvarande autentiseringsuppgifter och ersätt käll- och målnyckelrymderna 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 dubbel skrivning ä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 det timestamp är inställt på den aktuella tiden innan du läser alla data i källtabellen. writetime Sedan anges till den här bakåtdaterade tidsstämpeln. Detta säkerställer att poster som skrivs från den historiska datainläsningen till målslutpunkten inte kan skriva över uppdateringar som kommer in med en senare tidsstämpel från proxyn med dubbel skrivning medan historiska data läses.

Viktigt

Om du av någon anledning behöver bevara exakta tidsstämplar bör du använda en metod för historisk datamigrering som bevarar tidsstämplar, till exempel det här exemplet. Beroendeburken i exemplet innehåller också Spark-anslutningsappen, så du behöver inte installera Spark-anslutningssammansättningen som nämns i de tidigare kraven – om båda är installerade i Spark-klustret uppstår konflikter.

Verifiera källan och målet

När den historiska datainläsningen är klar bör databaserna vara synkroniserade och klara för snabb snabbning. Vi rekommenderar dock att du verifierar källan och målet för att säkerställa att de matchar innan de slutligen skärs över.

Anteckning

Om du använde cassandra-migratorexemplet som nämns ovan för att writetimebevara innehåller detta möjligheten att verifiera migreringen genom att jämföra rader i källa och mål baserat på vissa toleranser.

Nästa steg