使用雙重寫入 Proxy 即時移轉至 Azure Managed Instance for Apache Cassandra
可能的話,建議您使用 Apache Cassandra 原生功能,藉由設定混合式叢集,將資料從現有的叢集移轉至 Azure Managed Instance for Apache Cassandra。 這項功能會使用 Apache Cassandra 的 Gossip 通訊協定,以順暢的方式,將資料從來源資料中心複寫到新的受控執行個體資料中心。 不過,在某些情況下,您的來源資料庫版本不相容,或混合式叢集設定否則不可行。
本教學課程說明如何使用雙重寫入 Proxy 和 Apache Spark,以即時方式將資料移轉至 Azure Managed Instance for Apache Cassandra。 雙重寫入 Proxy 用來捕捉即時變更,而 Apache Spark 則用來大量複製歷程記錄資料。 此方法的優點包括:
- 應用程式變更最少。 Proxy 可以接受來自應用程式程式碼的連線,而不需要變更任何設定。 這會將所有要求路由傳送至來源資料庫,並以非同步方式將寫入路由傳送至次要目標。
- 用戶端連線通訊協定相依性。 由於此方法不相依於後端資源或內部通訊協定,因此可以搭配任何實作 Apache Cassandra 連線通訊協定的來源或目標 Cassandra 系統使用。
下圖說明此方法。
必要條件
使用 Azure 入口網站或 Azure CLI 佈建 Azure Managed Instance for Apache Cassandra 叢集。 請確定您可以使用 CQLSH 連線到叢集。
在您的受控 Cassandra 虛擬網路內佈建 Azure Databricks 帳戶。 請確定帳戶具有來源 Cassandra 叢集的網路存取權。 我們將在此帳戶中建立 Spark 叢集,以用於歷程記錄資料載入。
請確保您已將 keyspace/資料表配置從來源 Cassandra 資料庫移轉至目標 Cassandra 受控執行個體資料庫。
佈建 Spark 叢集
建議您選取支援 Spark 3.0 的 Azure Databricks Runtime 7.5 版。
新增 Spark 相依性
您必須將 Apache Spark Cassandra 連接器程式庫新增至叢集,以連線到任何與連線通訊協定相容的 Apache Cassandra 端點。 在您的叢集中,選取 [程式庫] > [安裝新的] > [Maven],然後在 Maven 座標中新增 com.datastax.spark:spark-cassandra-connector-assembly_2.12:3.0.0
。
重要
如果您需要在移轉期間針對每個資料列保留 Apache Cassandra writetime
,我們建議使用此範例。 此範例中的相依性 jar 也包含了 Spark 連接器,因此請留意您應該安裝的是此範例,而不是上述的連接器組件。 如果您想要在記錄資料載入完成後在來源與目標之間執行資料列比較驗證,此範例也能幫上忙。 如需詳細資訊,請參閱下方的「執行歷程記錄資料載入」和「驗證來源和目標」章節。
選取 [安裝],然後在安裝完成時重新啟動叢集。
注意
安裝 Cassandra 連接器程式庫之後,請務必重新啟動 Azure Databricks 叢集。
安裝雙重寫入 Proxy
為了在執行雙重寫入時能達到最佳效能,建議您在來源 Cassandra 叢集中的所有節點上安裝 Proxy。
#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
啟動雙重寫入 Proxy
建議您在來源 Cassandra 叢集中的所有節點上安裝 Proxy。 至少要執行下列命令,以在每個節點上啟動 Proxy。 將 <target-server>
取代為目標叢集中其中一個節點的 IP 或伺服器位址。 以本機 .jks 檔案的路徑取代 <path to JKS file>
,並以對應的密碼取代 <keystore password>
。
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>
以這種方式啟動 Proxy 便代表假設符合了下列條件:
- 來源和目標端點具有相同的使用者名稱和密碼。
- 來源和目標端點使用的是安全通訊端層 (SSL)。
如果您的來源和目標端點無法符合這些條件,請繼續閱讀以取得進一步的設定選項。
設定 SSL
針對 SSL,您可以執行現有的金鑰儲存區 (例如,您的來源叢集所使用的金鑰儲存區) 或使用 keytool
建立自我簽署憑證:
keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass password -validity 360 -keysize 2048
如果來源或目標端點未使用 SSL,您也可以停用 SSL。 使用 --disable-source-tls
或 --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
注意
當您透過 Proxy 建立對資料庫的 SSL 連線時,請確定您的用戶端應用程式所使用的金鑰儲存區和密碼,與用於雙重寫入 Proxy 的相同。
設定認證和連接埠
根據預設,來源認證將會從您的用戶端應用程式傳遞。 Proxy 將使用認證來連線到來源和目標叢集。 如先前所述,此程式會假設來源的認證和目標的認證相同。 啟動 Proxy 時,您可視需要分別為目標 Cassandra 端點指定不同的使用者名稱和密碼:
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>
若未特別指定,預設的來源和目標連接埠埠將會是 9042。 如果目標或來源 Cassandra 端點在不同的連接埠上執行,您可以使用 --source-port
或 --target-port
來指定不同的連接埠號碼:
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>
遠端部署 Proxy
在某些情況下,您可能不想將 Proxy 安裝在叢集節點本身,而是想要將它安裝在不同的電腦上。 在這種情況下,您必須指定 <source-server>
的 IP 位址:
java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar <source-server> <destination-server>
警告
若要在個別的電腦上遠端執行 Proxy (而不是在來源 Apache Cassandra 叢集中的所有節點上執行 Proxy),建議您將 Proxy 部署到與叢集中節點數量相同的電腦上,並依這裡所述,使用 Proxy 中的組態在 system.peers 中設定其 IP 位址的替換。 若未這麼做,可能會影響即時移轉時的效能,因為用戶端驅動程式將無法開啟與叢集內所有節點的連線。
毫不允許應用程式程式碼變更
根據預設,Proxy 會在連接埠 29042 上接聽。 應用程式程式碼必須變更為指向此連接埠。 不過,您可以變更 Proxy 所接聽的連接埠。 你可以透過下列方式來排除應用程式層級的程式碼變更:
- 讓來源 Cassandra 伺服器在不同的連接埠上執行。
- 讓 Proxy 在標準 Cassandra 連接埠 9042 上執行。
java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar source-server destination-server --proxy-port 9042
注意
在叢集節點上安裝 Proxy 並不需要重新啟動節點。 但是如果您有許多應用程式用戶端,而且想要讓 Proxy 在標準 Cassandra 連接埠 9042 上執行以避免任何應用層級的程式碼變更,您需要變更 Apache Cassandra 預設連接埠。 您接著必須重新啟動叢集中的節點,並將來源連接埠設定為您為來源 Cassandra 叢集定義的新連接埠。
在下列範例中,我們將來源 Cassandra 叢集變更為在連接埠 3074 上執行,然後在連接埠 9042 上啟動叢集:
java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar source-server destination-server --proxy-port 9042 --source-port 3074
強制通訊協定
Proxy 具有強制通訊協定的功能,在來源端點比目標更先進或不受支援時將可能需要使用功能。 在這種情況下,您可以指定 --protocol-version
和 --cql-version
來強制通訊協定與目標相符:
java -jar target/cassandra-proxy-1.0-SNAPSHOT-fat.jar source-server destination-server --protocol-version 4 --cql-version 3.11
在雙重寫入 Proxy 執行之後,您必須變更應用程式用戶端上的連接埠,然後重新啟動。 (如果您選擇該方法,您也能變更 Cassandra 連接埠,並重新啟動叢集。)Proxy 接著會開始將寫入轉接至目標端點。 您可以在此瞭解 Proxy 工具中可用的 監視和計量。
執行歷程資料載入
若要載入該資料,請在您的 Azure Databricks 帳戶中建立 Scala 筆記本。 將您的來源和目標 Cassandra 設定取代為對應的認證,以及來源和目標 keyspace 和資料表。 在下列範例中,視需要為每個資料表新增更多變數,然後執行。 在應用程式開始將要求傳送到雙重寫入 Proxy 之後,您即能開始轉移歷程記錄資料。
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
注意
在先前的 Scala 範例中,您會發現在讀取來源資料表中的所有資料之前,timestamp
將會設定為目前的時間。 然後,writetime
會設定為追溯的時間戳記。 這麼做能確保讀取歷程資料時,從歷程資料負載寫入至目標端點的紀錄,不會覆蓋掉帶有較晚時間戳記,來自雙重寫入 Proxy 的更新。
重要
如果您基於任何原因而需要保留「確切」的時間戳記,您應該採用歷程資料移轉方法來保留時間戳記,例如此範例。 範例中的相依性 jar 也包含了 Spark 連接器,因此您不需要安裝先前必要條件中所述的 Spark 連接器元件,因為在 Spark 叢集中同時安裝兩者將會造成衝突。
驗證來源和目標
在歷程資料載入完成後,您的資料庫應該已同步完成並準備好進行完全移轉。 不過,我們建議您先驗證來源和目標,以在完全移轉之前確保它們相符。
注意
如果您使用上述的Cassandra 移轉程式範例來保留 writetime
,這包括了藉由根據特定容錯度來比較來源和目標中的資料列,以驗證移轉的能力。