如果您需要將MySQL中的增量資料即時同步至Elasticsearch(簡稱ES)執行個體,且您對資料同步的即時性要求較高,可以通過Canal來實現。
背景資訊
Canal是阿里巴巴集團提供的一個開源產品,能夠通過解析資料庫的增量日誌,提供增量資料的訂閱和消費功能。Canal的功能原理及詳細說明請參見Canal。使用Canal類比成MySQL的Slave,即時接收MySQL的增量資料binlog,然後通過RESTful API將資料寫入到阿里雲ES執行個體中,適用於對資料同步的即時性要求較高的情境。
前提條件
已建立RDS MySQL執行個體、阿里雲ES執行個體、阿里雲ECS執行個體。建議您在同一專用網路下建立相關執行個體。
已建立RDS MySQL執行個體。具體操作請參見建立RDS MySQL執行個體。本文以MySQL 5.7版本為例。
已建立阿里雲ES執行個體。具體操作請參見建立Elasticsearch執行個體。本文以阿里雲ES 6.7核心增強版為例。
說明通過canal將資料寫入到ES執行個體中,需將阿里雲ECS執行個體的IP地址加入ES執行個體中。具體操作,請參見配置ES執行個體公網或私網訪問白名單。
已建立阿里雲ECS執行個體。用於部署Canal-server和Canal-adapter。具體操作請參見自訂購買執行個體。本文建立的執行個體的鏡像為CentOS 7.6 64位。
使用限制
本方案僅支援將MySQL增量資料同步至阿里雲ES。
安裝的JDK版本必須大於等於1.8.0。
Canal 1.1.4版本不支援ES 7.x版本。
ES 7.x版本的資料寫入需使用Canal 1.1.5版本,ES 8.x版本請選擇1.1.7版本。您也可以通過其他方式(例如Logstash、DTS)實現MySQL資料同步。
在進行資料同步時支援自訂索引Mapping,但需保證Mapping中定義的欄位(名稱+類型)與MySQL中一致。
本方案需要您自行保證Canal的可用性,避免出現業務不可用或故障。例如:當出現ECS重啟,Canal異常退出等情境時如何繼續同步資料等。
Canal Adapter不支援使用HTTPS協議串連阿里雲ES執行個體。
操作步驟
步驟一:準備MySQL資料來源
進入RDS控制台,建立RDS MySQL資料庫和表。具體操作請參見RDS MySQL快速入門。本文使用的建表語句如下。
-- create table
CREATE TABLE `es_test` (
`id` bigint(32) NOT NULL,
`name` text NOT NULL,
`count` text NOT NULL,
`color` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB
DEFAULT CHARACTER SET=utf8;
步驟二:建立索引
登入目標阿里雲ES執行個體的Kibana控制台,具體操作請參見登入Kibana控制台。
說明本文以阿里雲ES 6.7.0版本為例,其他版本操作可能略有差別,請以實際介面為準。
- 在左側導覽列,單擊Dev Tools。
在Console中,執行以下命令建立索引。
以下樣本建立的索引名稱為es_test,包含count、id、name和color欄位。
重要mappings中的欄位需要與步驟一:準備MySQL資料來源中建立的欄位(名稱和類型)保持一致。
PUT es_test?include_type_name=true { "settings" : { "index" : { "number_of_shards" : "5", "number_of_replicas" : "1" } }, "mappings" : { "_doc" : { "properties" : { "count": { "type": "text" }, "id": { "type": "integer" }, "name": { "type" : "text", "analyzer": "ik_smart" }, "color" : { "type" : "text" } } } } }
建立成功後,返回如下結果。
{ "acknowledged" : true, "shards_acknowledged" : true, "index" : "es_test" }
步驟三:安裝JDK
串連ECS執行個體。
具體操作請參見通過密碼或密鑰認證登入Linux執行個體。
說明本文檔以普通使用者權限為例。
查看可用的JDK軟體包列表。
sudo yum search java | grep -i --color JDK
選擇合適的版本,安裝JDK。
本文選擇java-1.8.0-openjdk-devel.x86_64。
sudo yum install java-1.8.0-openjdk-devel.x86_64
配置環境變數。
開啟etc檔案夾下的profile檔案。
vim ~/.bash_profile
在檔案內添加如下的環境變數。
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.362.b08-1.el7_9.x86_64 export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export PATH=$PATH:$JAVA_HOME/bin
重要JAVA_HOME需要替換為您JDK的安裝路徑,可通過
find / -name 'java'
命令查看。按下Esc鍵,然後使用
:wq
儲存檔案並退出vi模式,隨後執行以下命令使配置生效。source ~/.bash_profile
執行以下命令,驗證JDK是否安裝成功。
java -version
顯示如下結果說明JDK安裝成功。
openjdk version "1.8.0_362" OpenJDK Runtime Environment (build 1.8.0_362-b08) OpenJDK 64-Bit Server VM (build 25.362-b08, mixed mode)
步驟四:安裝並啟動Canal-server
下載Canal-server。
本文使用1.1.4版本。
wget https://github.com/alibaba/canal/releases/download/canal-1.1.4/canal.deployer-1.1.4.tar.gz
說明目前Canal 1.1.5版本已支援ES 7.0版本,如果您使用的是ES 7.0,需要下載Canal 1.1.5版本。詳細資料請參見Canal release note。
下載Canal-server和Canal-adapter需要串連公網,請確保ECS執行個體可以訪問公網。
解壓。
tar -zxvf canal.deployer-1.1.4.tar.gz
修改
conf/example/instance.properties
檔案。vi conf/example/instance.properties
配置項
說明
canal.instance.master.address
需要設定為<RDS MySQL資料庫的內網地址>:<內網連接埠>,相關資訊可在RDS MySQL執行個體的基本資料頁面擷取。例如rm-bp1u1xxxxxxxxx6ph.mysql.rds.aliyuncs.com:3306。
canal.instance.dbUsername
RDS MySQL資料庫的帳號名稱,可在執行個體的帳號管理頁面擷取。
canal.instance.dbPassword
RDS MySQL資料庫的密碼。
按下Esc鍵,然後使用
:wq
命令儲存檔案並退出vi模式。啟動Canal-server,並查看日誌。
./bin/startup.sh cat logs/canal/canal.log
步驟五:安裝並啟動Canal-adapter
下載Canal-adapter。
本文使用1.1.4版本。
wget https://github.com/alibaba/canal/releases/download/canal-1.1.4/canal.adapter-1.1.4.tar.gz
說明目前Canal 1.1.5版本已支援ES 7.0版本,如果您使用的是ES 7.0,需要下載Canal 1.1.5版本。詳細資料請參見Canal release note。
下載Canal-server和Canal-adapter需要串連公網,請確保ECS執行個體可以訪問公網。
解壓。
tar -zxvf canal.adapter-1.1.4.tar.gz
修改
conf/application.yml
檔案。vi conf/application.yml
配置項
說明
canal.conf.canalServerHost
canalDeployer訪問地址。保持預設(127.0.0.1:11111)即可。
canal.conf.srcDataSources.defaultDS.url
需要設定為jdbc:mysql://<RDS MySQL內網地址>:<內網連接埠>/<資料庫名稱>?useUnicode=true,相關資訊可在RDS MySQL執行個體的基本資料頁面擷取。例如jdbc:mysql://rm-bp1xxxxxxxxxnd6ph.mysql.rds.aliyuncs.com:3306/elasticsearch?useUnicode=true。
canal.conf.srcDataSources.defaultDS.username
RDS MySQL資料庫的帳號名稱,可在RDS MySQL執行個體的帳號管理頁面擷取。
canal.conf.srcDataSources.defaultDS.password
RDS MySQL資料庫的密碼。
canal.conf.canalAdapters.groups.outerAdapters.hosts
定位到name:es的位置,將hosts替換為<ES執行個體的內網地址>:<內網連接埠>,相關資訊可在ES執行個體的基本資料頁面擷取。例如,es-cn-v64xxxxxxxxx3medp.elasticsearch.aliyuncs.com:9200。
canal.conf.canalAdapters.groups.outerAdapters.mode
必須設定為rest。
canal.conf.canalAdapters.groups.outerAdapters.properties.security.auth
需要設定為<ES執行個體的帳號>:<密碼>。例如elastic:es_password。
canal.conf.canalAdapters.groups.outerAdapters.properties.cluster.name
ES執行個體的ID,可在ES執行個體的基本資料頁面擷取。例如es-cn-v64xxxxxxxxx3medp。
按下Esc鍵,然後使用
:wq
命令儲存檔案並退出vi模式。同樣的方式,修改
conf/es/*.yml
檔案,定義MySQL資料到ES資料的映射欄位。啟動Canal-adapter服務,並查看日誌。
./bin/startup.sh cat logs/adapter/adapter.log
說明本文以MySQL 5.7版本為例,如果您使用的是MySQL其它版本,需要將MySQL磁碟機替換為相應的版本,否則可能會導致啟動失敗,詳細資料請參見常見問題。
服務啟動正常時,結果如下所示。
步驟六:驗證增量資料同步
在RDS MySQL資料庫中,新增、修改或刪除資料庫中es_test表的資料。
insert `ES`.`es_test`(`count`,`id`,`name`,`color`) values('11',2,'canal_test2','red');
登入目標阿里雲ES執行個體的Kibana控制台,具體操作請參見登入Kibana控制台。
- 在左側導覽列,單擊Dev Tools。
在Console中,執行以下命令查詢同步成功的資料。
GET /es_test/_search
預期結果如下。
重要Canal同步的是增量資料,不會同步之前的存量資料。
常見問題
Q:啟動Canal-adapter時,adapter.log日誌顯示異常,如何解決?錯誤記錄檔為:java.lang.RuntimeException: java.lang.RuntimeException: java.lang.ClassCastException: com.alibaba.druid.pool.DruidDataSource cannot be cast to com.alibaba.druid.pool.DruidDataSource
at com.alibaba.otter.canal.client.adapter.es7x.ES7xAdapter.init(ES7xAdapter.java:54) ~[client-adapter.es7x-1.1.5-jar-with-dependencies.jar:na]
A:將canal.adapter-1.1.5\plugin下的client-adapter.es7x-1.1.5-jar-with-dependencies.jar替換為canal-1.1.5-alpha-2版本下的對應檔案。
您可以參考Canal的issues解決,請參見Canal issues
以root許可權使用者為例,操作步驟如下:
下載canal-1.1.5-alpha-2版本。詳細資料請參見Canal release note。
wget https://github.com/alibaba/canal/releases/download/canal-1.1.5-alpha-2/canal.adapter-1.1.5-SNAPSHOT.tar.gz
解壓檔案。
tar -zxvf canal.adapter-1.1.5-SNAPSHOT.tar.gz
拷貝canal-1.1.5-alpha-2 版本中plugin下的client-adapter.es7x-1.1.5-SNAPSHOT-jar-with-dependencies.jar放到canal.adapter-1.1.5\plugin目錄下。
說明實際拷貝檔案的目錄需根據您建立的目錄結構來。
cp canal.adapter-1.1.5-SNAPSHOT/plugin/client-adapter.es7x-1.1.5-SNAPSHOT-jar-with-dependencies.jar canal/canal.adapter/plugin
刪除canal.adapter-1.1.5\plugin下的client-adapter.es7x-1.1.5-jar-with-dependencies.jar。
rm -rf client-adapter.es7x-1.1.5-jar-with-dependencies.jar
修改名字。
mv client-adapter.es7x-1.1.5-SNAPSHOT-jar-with-dependencies.jar client-adapter.es7x-1.1.5-jar-with-dependencies.jar
Q:啟動Canal-adapter時,adapter.log日誌顯示異常,如何解決?錯誤記錄檔為java.sql.SQLException: Unknown system variable 'query_cache_size'
A:可能是由於Canal-adapter中內建的MySQL驅動版本與串連的MySQL資料庫版本不一致導致,例如:使用的canal.adapter-1.1.4時,其內建的MySQL磁碟機為mysql-connector-java-5.1.40.jar,在串連MySQL8時就會出現如上所述的異常資訊。可更換Canal-adapter中的MySQL磁碟機版本進行解決。
Q:使用Canal同步MySQL 8.0版本的資料,如何將MySQL磁碟機版本替換成8.0?
A:以下操作步驟以root許可權使用者為例。
下載8.0版本的MySQL磁碟機。
wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.29.zip
解壓。
unzip mysql-connector-java-8.0.29.zip
拷貝檔案到Canal-adapter的lib目錄下。
mv mysql-connector-java-8.0.29/mysql-connector-java-8.0.29.jar lib/
添加許可權。
chmod 777 lib/mysql-connector-java-8.0.29.jar chmod +st lib/mysql-connector-java-8.0.29.jar
刪除5.x版本的磁碟機。
rm -rf lib/mysql-connector-java-5.1.40.jar