Compartilhar via


Migração dinâmica para a Instância Gerenciada do Azure para Apache Cassandra usando um proxy de gravação dupla

Sempre que possível, recomendamos que você use a funcionalidade nativa do Apache Cassandra para migrar dados do cluster existente para a Instância Gerenciada do Azure para Apache Cassandra configurando um cluster híbrido. Essa capacidade usa o protocolo gossip do Apache Cassandra para replicar dados do data center de origem para seu novo datacenter de instância gerenciada de maneira perfeita.

Pode haver alguns cenários em que a versão do banco de dados de origem não seja compatível ou uma configuração de cluster híbrido não seja viável. Este tutorial descreve como migrar dados para a Instância Gerenciada do Azure para Apache Cassandra de maneira dinâmica usando um proxy de gravação dupla e o Apache Spark. O proxy de gravação dupla é usado para capturar alterações ao vivo, enquanto os dados históricos são copiados em massa usando o Apache Spark. Os benefícios dessa abordagem são:

  • Alterações mínimas no aplicativo. O proxy pode aceitar conexões do código do aplicativo com pouca ou nenhuma alteração de configuração. Ele roteia todas as solicitações para o banco de dados de origem e roteia as gravações de forma assíncrona para um destino secundário.
  • Dependência de protocolo de conexão de cliente. Como essa abordagem não depende de recursos de back-end ou protocolos internos, ela pode ser usada com qualquer sistema cassandra de origem ou de destino que implemente o protocolo de transmissão do Apache Cassandra.

A imagem a seguir ilustra a abordagem.

Animação que mostra a migração dinâmica de dados para a Instância Gerenciada do Azure para Apache Cassandra.

Pré-requisitos

Provisionar um cluster Spark

Recomendamos que você selecione o runtime do Azure Databricks versão 7.5, que dá suporte ao Spark 3.0.

Captura de tela que mostra a localização da versão de runtime do Azure Databricks.

Adicionar dependências do Spark

Você precisa adicionar a biblioteca do Conector do Apache Spark Cassandra ao cluster para se conectar aos pontos de extremidade compatíveis do protocolo eletrônico do Apache Cassandra. No cluster, selecione Bibliotecas>Instalar novo>Maven e, em seguida, adicione com.datastax.spark:spark-cassandra-connector-assembly_2.12:3.0.0 nas coordenadas do Maven.

Importante

Se você tiver um requisito para preservar o writetime do Apache Cassandra para cada linha durante a migração, recomendamos usar esta amostra. O jar de dependência neste exemplo também contém o conector spark, portanto, instale essa versão em vez do assembly do conector.

Este exemplo também será útil, se você quiser executar uma validação de comparação de linha entre a origem e o destino, após a conclusão da carga de dados histórica. Consulte Executar a carga de dados históricos e validar a origem e o destino.

Captura de tela que mostra a pesquisa dos pacotes Maven no Azure Databricks.

Selecione Instalar e reinicie o cluster quando a instalação for concluída.

Observação

Verifique se reinicia o cluster do Azure Databricks após a instalação da biblioteca do Cassandra Connector.

Instalar o proxy de gravação dupla

Para obter um desempenho ideal durante gravações duplas, recomendamos que você instale o proxy em todos os nós no cluster do Cassandra de origem.

#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

Iniciar o proxy de gravação dupla

Recomendamos instalar o proxy em todos os nós do cluster do Cassandra de origem. No mínimo, execute o comando a seguir para iniciar o proxy em cada nó. Substitua <target-server> por um endereço IP ou de servidor de um dos nós no cluster de destino. Substitua <path to JKS file> pelo caminho para um arquivo jks local e substitua <keystore password> pela senha correspondente.

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>

Ao iniciar o proxy dessa maneira, pressupõe-se que o seguinte é verdadeiro:

  • O nome de usuário e a senha dos pontos de extremidade de origem e de destino são iguais.
  • Os pontos de extremidade de origem e destino implementam protocolo SSL.

Se os pontos de extremidade de origem e destino não atenderem a esses critérios, continue lendo para obter mais opções de configuração.

Configurar SSL

Para SSL, você pode implementar um repositório de chaves existente, por exemplo, aquele que o cluster de origem usa ou criar um certificado autoassinado usando keytool:

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

Você também poderá desabilitar o SSL para pontos de extremidade de origem ou de destino caso eles não implementem o SSL. Use os sinalizadores --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 

Observação

Verifique se o aplicativo cliente usa o mesmo repositório de chaves e senha que os usados para o proxy de gravação dupla quando você cria conexões SSL com o banco de dados que usa o proxy.

Configurar as credenciais e a porta

Por padrão, as credenciais de origem são transferidas através do aplicativo cliente. O proxy usa as credenciais para fazer conexões com os clusters de origem e de destino. Como mencionado antes, esse processo pressupõe que as credenciais de origem e de destino são as mesmas. Se for necessário, você pode especificar um nome de usuário e senha diferentes para o ponto de extremidade do Cassandra de destino separadamente ao iniciar o 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>

As portas de origem e destino padrão, quando não especificadas, são 9042. Caso os pontos de extremidade do Cassandra de origem ou de destino sejam executados em uma porta diferente, você poderá usar --source-port ou --target-port para especificar um número de porta diferente:

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>

Implantar o proxy remotamente

Pode haver circunstâncias em que você não deseja instalar o proxy nos próprios nós de cluster. Você deseja instalá-lo em um computador separado. Nesse cenário, especifique o endereço IP de <source-server>:

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

Aviso

Talvez você queira executar o proxy remotamente em um computador separado em vez de executá-lo em todos os nós no cluster do Apache Cassandra de origem. Nesse caso, recomendamos implantar o proxy no mesmo número de computadores que você tem nós em seu cluster. Configure uma substituição para seus endereços IP em system.peers. Use essa configuração no proxy. Se você não usar essa abordagem, isso poderá afetar o desempenho durante a migração ao vivo, pois o driver do cliente não pode abrir conexões com todos os nós no cluster.

Permitir alterações de código de aplicativo zero

Por padrão, o proxy escuta na porta 29042. Você deve alterar o código do aplicativo para apontar para essa porta. Como alternativa, você pode alterar a porta na qual o proxy escuta. Você poderá usar essa abordagem se quiser eliminar as alterações de código no nível do aplicativo:

  • Fazendo com que o servidor Cassandra de origem seja executado em uma porta diferente.
  • Fazendo com que o proxy seja executado na porta Cassandra padrão 9042.
java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar source-server destination-server --proxy-port 9042

Observação

A instalação do proxy em nós de cluster não requer a reinicialização dos nós. Se você tiver muitos clientes de aplicativo e preferir executar o proxy na porta cassandra padrão 9042 para eliminar quaisquer alterações de código no nível do aplicativo, altere a porta padrão do Apache Cassandra. Em seguida, você precisará reiniciar os nós no cluster e configurar a porta de origem como a nova porta que você definiu para o cluster Cassandra de origem.

No exemplo a seguir, alteramos o cluster Cassandra de origem para execução na porta 3074 e iniciamos o cluster na porta 9042:

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

Forçar protocolos

O proxy tem funcionalidade para forçar protocolos, as quais podem ser necessárias se o ponto de extremidade de origem for mais avançado do que o de destino ou ele se não tiver suporte. Nesse caso, você pode especificar que --protocol-version e --cql-version forcem o protocolo a obedecer ao destino:

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

Depois que o proxy de gravação dupla estiver em execução, altere a porta no cliente do aplicativo e reinicie. Ou altere a porta do Cassandra e reinicie o cluster se você escolheu essa abordagem. O proxy inicia o encaminhamento de gravações para o ponto de extremidade de destino. Você pode saber mais sobre monitoramento e métricas disponíveis na ferramenta de proxy.

Executar o carregamento de dados históricos

Para carregar os dados, crie um notebook Scala em sua conta do Azure Databricks. Substitua as configurações do Cassandra de origem e de destino pelas credenciais correspondentes e substitua os keyspaces e as tabelas de origem e de destino. Adicione mais variáveis para cada tabela conforme necessário para o exemplo a seguir e faça a execução. Depois que o aplicativo começar a enviar solicitações para o proxy de gravação dupla, estará tudo pronto para a migração de dados históricos.

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

Observação

No exemplo Scala anterior, timestamp está sendo configurado como a hora atual antes de ler todos os dados na tabela de origem. Em seguida, writetime será definido para esse carimbo de data/hora retroativo. Essa abordagem garante que os registros gravados da carga de dados históricos para o ponto de extremidade de destino não possam substituir as atualizações que chegam com um carimbo de data/hora posterior do proxy de gravação dupla enquanto os dados históricos estão sendo lidos.

Importante

Se você precisar preservar os carimbos de data/hora exatos por algum motivo, deverá adotar uma abordagem de migração de dados históricos que preserve os carimbos de data/hora, como este exemplo. O jar de dependência no exemplo também contém o conector spark, portanto, você não precisa instalar o assembly do conector Spark mencionado nos pré-requisitos anteriores. Ter ambos instalados em seu cluster Spark causa conflitos.

Validar a origem e o destino

Após o carregamento de dados históricos ser concluído, seus bancos de dados deverão estar em sincronia e prontos para a substituição. Recomendamos que você valide a origem e o destino para garantir que eles correspondam entre si antes de finalmente transferir.

Observação

Se você tiver usado a amostra do migrador do Cassandra mencionado nas seções anteriores para preservação de writetime, terá a capacidade de validar a migraçãocomparando linhas na origem e no destino com base em determinadas tolerâncias.

Próxima etapa