Canal-adapter的簡單配置


項目的需求是mysql到mysql

一、首先需要安裝canal-server,之前的博客也簡單寫過,這就跳過了。

image-20201126155811845

二、配置canal.adapter

  1. 下載canal.adapter 解壓 https://github.com/alibaba/canal/releases
  2. 編輯application.yml
server:
  port: 8081
spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    default-property-inclusion: non_null

canal.conf:
  mode: tcp # kafka rocketMQ
  canalServerHost: 127.0.0.1:11111
#  zookeeperHosts: slave1:2181
#  mqServers: 127.0.0.1:9092 #or rocketmq
#  flatMessage: true
  batchSize: 500
  syncBatchSize: 1000
  retries: 0
  timeout:
  accessKey:
  secretKey:
  srcDataSources:
    demoSrc:
      url: jdbc:mysql://192.168.1.104:3308/canal?useUnicode=true
      username: root
      password: root
  canalAdapters:
  - instance: example # canal instance Name or mq topic name
    groups:
    - groupId: g1
      outerAdapters:
      - name: logger
      - name: rdb
        key: demoDes
        properties:
          jdbc.driverClassName: com.mysql.jdbc.Driver
          jdbc.url: jdbc:mysql://192.168.1.104:3308/test?useUnicode=true
          jdbc.username: root
          jdbc.password: root
#      - name: rdb
#        key: oracle1
#        properties:
#          jdbc.driverClassName: oracle.jdbc.OracleDriver
#          jdbc.url: jdbc:oracle:thin:@localhost:49161:XE
#          jdbc.username: mytest
#          jdbc.password: m121212
#      - name: rdb
#        key: postgres1
#        properties:
#          jdbc.driverClassName: org.postgresql.Driver
#          jdbc.url: jdbc:postgresql://localhost:5432/postgres
#          jdbc.username: postgres
#          jdbc.password: 121212
#          threads: 1
#          commitSize: 3000
#      - name: hbase
#        properties:
#          hbase.zookeeper.quorum: 127.0.0.1
#          hbase.zookeeper.property.clientPort: 2181
#          zookeeper.znode.parent: /hbase
#      - name: es
#        hosts: 127.0.0.1:9300 # 127.0.0.1:9200 for rest mode
#        properties:
#          mode: transport # or rest
#          # security.auth: test:123456 #  only used for rest mode
#          cluster.name: elasticsearch
adapter.conf:
  datasourceConfigs:                # 數據源配置列表, 數據源將在適配器中用於ETL、數據同步回查等使用
    defaultDS:                      # 數據源 dataSourceKey, 適配器中通過該值獲取指定數據源
      url: jdbc:mysql://192.168.1.104:3308/canal?useUnicode=true
      username: root
      password: root
  adapterConfigs:                   # 適配器內部配置列表
  - rdb/book.yml
  - rdb/cluster.yml

注意,最后這段是我參考官網的,寫多個文件對應多個表

dataSourceKey: demoSrc
destination: example
groupId: g1
outerAdapterKey: demoDes
concurrent: true
dbMapping:
  database: canal
  table: tb_book2
  targetTable: test.tb_book2
  targetPk:
    id: id
  mapAll: true
  etlCondition: "where c_time>={}"
  commitBatch: 3000 # 批量提交的大小

注意如果是多個主鍵可以換行對應

三、測試

image-20201126155845439

其他的配置可以查看官網

基本說明

canal 1.1.1版本之后, 增加客戶端數據落地的適配及啟動功能, 目前支持功能:

  • 客戶端啟動器
  • 同步管理REST接口
  • 日志適配器, 作為DEMO
  • HBase的數據同步(表對表同步), ETL功能
  • (后續支持) ElasticSearch多表數據同步,ETL功能

環境版本

  • 操作系統:無要求
  • java版本: jdk1.8 以上
  • canal 版本: 請下載最新的安裝包,本文以當前v1.1.1 的canal.deployer-1.1.1.tar.gz為例
  • MySQL版本 :5.7.18
  • HBase版本: Apache HBase 1.1.2, 若和服務端版本不一致可自行替換客戶端HBase依賴

一、適配器啟動器

client-adapter分為適配器和啟動器兩部分, 適配器為多個fat jar, 每個適配器會將自己所需的依賴打成一個包, 以SPI的方式讓啟動器動態加載

啟動器為 SpringBoot 項目, 支持canal-client啟動的同時提供相關REST管理接口, 運行目錄結構為:

- bin
    restart.sh
    startup.bat
    startup.sh
    stop.sh
- lib
    client-adapter.logger-1.1.1-jar-with-dependencies.jar
    client-adapter.hbase-1.1.1-jar-with-dependencies.jar
    ...
- conf
    application.yml
    - hbase
        mytest_person2.yml
- logs

以上目錄結構最終會打包成 canal-adapter-launcher.tar.gz 壓縮包

二、啟動器

2.1 啟動器配置 application.yml

canal相關配置部分說明

canal.conf:
  canalServerHost: 127.0.0.1:11111  # 對應單機模式下的canal server的ip:port
  zookeeperHosts: slave1:2181       # 對應集群模式下的zk地址, 如果配置了canalServerHost, 則以canalServerHost為准
  bootstrapServers: slave1:6667     # kafka或rocketMQ地址, 與canalServerHost不能並存
  flatMessage: true                 # 扁平message開關, 是否以json字符串形式投遞數據, 僅在kafka/rocketMQ模式下有效
  canalInstances:                   # canal實例組, 如果是tcp模式可配置此項
  - instance: example               # 對應canal destination
    groups:                  # 對應適配器分組, 分組間的適配器並行運行
    - outAdapters:                  # 適配器列表, 分組內的適配串行運行
      - name: logger                # 適配器SPI名
      - name: hbase
        properties:                 # HBase相關連接參數
          hbase.zookeeper.quorum: slave1
          hbase.zookeeper.property.clientPort: 2181
          zookeeper.znode.parent: /hbase
  mqTopics:                         # MQ topic組, 如果是kafka或者rockeMQ模式可配置此項, 與canalInstances不能並存
  - mqMode: kafka                   # MQ的模式: kafak/rocketMQ
    topic: example                  # MQ topic
    groups:                         # group組
    - groupId: g2                   # group id
      outAdapters:                  # 適配器列表, 以下配置和canalInstances中一樣
      - name: logger                

適配器相關配置部分說明

adapter.conf:
  datasourceConfigs:                # 數據源配置列表, 數據源將在適配器中用於ETL、數據同步回查等使用
    defaultDS:                      # 數據源 dataSourceKey, 適配器中通過該值獲取指定數據源
      url: jdbc:mysql://127.0.0.1:3306/mytest?useUnicode=true
      username: root
      password: 121212
  adapterConfigs:                   # 適配器內部配置列表
  - hbase/mytest_person2.yml        # 類型/配置文件名, 這里示例就是對應HBase適配器hbase目錄下的mytest_person2.yml文件

2.2 同步管理REST接口

2.2.1 查詢所有訂閱同步的canal destination或MQ topic

curl http://127.0.0.1:8081/destinations

2.2.2 數據同步開關

curl http://127.0.0.1:8081/syncSwitch/example/off -X PUT

針對 example 這個canal destination/MQ topic 進行開關操作. off代表關閉, 該destination/topic下的同步將阻塞或者斷開連接不再接收數據, on代表開啟

注: 如果在配置文件中配置了 zookeeperHosts 項, 則會使用分布式鎖來控制HA中的數據同步開關, 如果是單機模式則使用本地鎖來控制開關

2.2.3 數據同步開關狀態

curl http://127.0.0.1:8081/syncSwitch/example

查看指定 canal destination/MQ topic 的數據同步開關狀態

2.2.4 手動ETL

curl http://127.0.0.1:8081/etl/hbase/mytest_person2.yml -X POST -d "params=2018-10-21 00:00:00"

導入數據到指定類型的庫

2.2.5 查看相關庫總數據

curl http://127.0.0.1:8081/count/hbase/mytest_person2.yml

2.3 啟動canal-adapter示例

2.3.1 啟動canal server (單機模式), 參考: Canal QuickStart

2.3.2 修改conf/application.yml為:

server:
  port: 8081
logging:
  level:
    com.alibaba.otter.canal.client.adapter.hbase: DEBUG
spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    default-property-inclusion: non_null

canal.conf:
  canalServerHost: 127.0.0.1:11111
  flatMessage: true
  canalInstances:
  - instance: example
    adapterGroups:
    - outAdapters:
      - name: logger

啟動

bin/startup.sh

三、HBase適配器

3.1 修改啟動器配置: application.yml

server:
  port: 8081
logging:
  level:
    com.alibaba.otter.canal.client.adapter.hbase: DEBUG
spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    default-property-inclusion: non_null

canal.conf:
  canalServerHost: 127.0.0.1:11111
  flatMessage: true
  srcDataSources:
    defaultDS:
      url: jdbc:mysql://127.0.0.1:3306/mytest?useUnicode=true
      username: root
      password: 121212
  canalInstances:
  - instance: example
    adapterGroups:
    - outAdapters:
      - name: hbase
        properties:
          hbase.zookeeper.quorum: slave1
          hbase.zookeeper.property.clientPort: 2181
          zookeeper.znode.parent: /hbase

adapter將會自動加載 conf/hbase 下的所有.yml結尾的配置文件

3.2 適配器表映射文件

修改 conf/hbase/mytest_person.yml文件:

dataSourceKey: defaultDS            # 對應application.yml中的datasourceConfigs下的配置
hbaseMapping:                       # mysql--HBase的單表映射配置
  mode: STRING                      # HBase中的存儲類型, 默認統一存為String, 可選: #PHOENIX  #NATIVE   #STRING 
                                    # NATIVE: 以java類型為主, PHOENIX: 將類型轉換為Phoenix對應的類型
  destination: example              # 對應 canal destination/MQ topic 名稱
  database: mytest                  # 數據庫名/schema名
  table: person                     # 表名
  hbaseTable: MYTEST.PERSON         # HBase表名
  family: CF                        # 默認統一Column Family名稱
  uppercaseQualifier: true          # 字段名轉大寫, 默認為true
  commitBatch: 3000                 # 批量提交的大小, ETL中用到
  #rowKey: id,type                  # 復合字段rowKey不能和columns中的rowKey並存
                                    # 復合rowKey會以 '|' 分隔
  columns:                          # 字段映射, 如果不配置將自動映射所有字段, 
                                    # 並取第一個字段為rowKey, HBase字段名以mysql字段名為主
    id: ROWKE                       
    name: CF:NAME
    email: EMAIL                    # 如果column family為默認CF, 則可以省略
    type:                           # 如果HBase字段和mysql字段名一致, 則可以省略
    c_time: 
    birthday: 

如果涉及到類型轉換,可以如下形式:

...
  columns:                         
    id: ROWKE$STRING                      
    ...                   
    type: TYPE$BYTE                          
    ...

類型轉換涉及到Java類型和Phoenix類型兩種, 分別定義如下:

#Java 類型轉換, 對應配置 mode: NATIVE
$DEFAULT
$STRING
$INTEGER
$LONG
$SHORT
$BOOLEAN
$FLOAT
$DOUBLE
$BIGDECIMAL
$DATE
$BYTE
$BYTES
#Phoenix 類型轉換, 對應配置 mode: PHOENIX
$DEFAULT                  對應PHOENIX里的VARCHAR
$UNSIGNED_INT             對應PHOENIX里的UNSIGNED_INT           4字節
$UNSIGNED_LONG            對應PHOENIX里的UNSIGNED_LONG          8字節
$UNSIGNED_TINYINT         對應PHOENIX里的UNSIGNED_TINYINT       1字節
$UNSIGNED_SMALLINT        對應PHOENIX里的UNSIGNED_SMALLINT      2字節
$UNSIGNED_FLOAT           對應PHOENIX里的UNSIGNED_FLOAT         4字節
$UNSIGNED_DOUBLE          對應PHOENIX里的UNSIGNED_DOUBLE        8字節
$INTEGER                  對應PHOENIX里的INTEGER                4字節
$BIGINT                   對應PHOENIX里的BIGINT                 8字節
$TINYINT                  對應PHOENIX里的TINYINT                1字節
$SMALLINT                 對應PHOENIX里的SMALLINT               2字節
$FLOAT                    對應PHOENIX里的FLOAT                  4字節
$DOUBLE                   對應PHOENIX里的DOUBLE                 8字節
$BOOLEAN                  對應PHOENIX里的BOOLEAN                1字節
$TIME                     對應PHOENIX里的TIME                   8字節
$DATE                     對應PHOENIX里的DATE                   8字節
$TIMESTAMP                對應PHOENIX里的TIMESTAMP              12字節
$UNSIGNED_TIME            對應PHOENIX里的UNSIGNED_TIME          8字節
$UNSIGNED_DATE            對應PHOENIX里的UNSIGNED_DATE          8字節
$UNSIGNED_TIMESTAMP       對應PHOENIX里的UNSIGNED_TIMESTAMP     12字節
$VARCHAR                  對應PHOENIX里的VARCHAR                動態長度
$VARBINARY                對應PHOENIX里的VARBINARY              動態長度
$DECIMAL                  對應PHOENIX里的DECIMAL                動態長度

如果不配置將以java對象原生類型默認映射轉換

3.3 啟動HBase數據同步

創建HBase表

在HBase shell中運行:

create 'MYTEST.PERSON', {NAME=>'CF'}

啟動canal-adapter啟動器

bin/startup.sh

驗證

修改mysql mytest.person表的數據, 將會自動同步到HBase的MYTEST.PERSON表下面, 並會打出DML的log

四、關系型數據庫適配器

RDB adapter 用於適配mysql到任意關系型數據庫(需支持jdbc)的數據同步及導入

4.1 修改啟動器配置: application.yml, 這里以oracle目標庫為例

server:
  port: 8081
logging:
  level:
    com.alibaba.otter.canal.client.adapter.rdb: DEBUG
......

canal.conf:
  canalServerHost: 127.0.0.1:11111
  srcDataSources:
    defaultDS:
      url: jdbc:mysql://127.0.0.1:3306/mytest?useUnicode=true
      username: root
      password: 121212
  canalInstances:
  - instance: example
    groups:
    - outAdapters:
      - name: rdb                                               # 指定為rdb類型同步
        key: oracle1                                            # 指定adapter的唯一key, 與表映射配置中outerAdapterKey對應
        properties:
          jdbc.driverClassName: oracle.jdbc.OracleDriver        # jdbc驅動名, jdbc的jar包需要自行放致lib目錄下
          jdbc.url: jdbc:oracle:thin:@localhost:49161:XE        # jdbc url
          jdbc.username: mytest                                 # jdbc username
          jdbc.password: m121212                                # jdbc password
          threads: 5                                            # 並行執行的線程數, 默認為1
          commitSize: 3000                                      # 批次提交的最大行數

其中 outAdapter 的配置: name統一為rdb, key為對應的數據源的唯一標識需和下面的表映射文件中的outerAdapterKey對應, properties為目標庫jdb的相關參數 adapter將會自動加載 conf/rdb 下的所有.yml結尾的表映射配置文件

4.2 適配器表映射文件

修改 conf/rdb/mytest_user.yml文件:

dataSourceKey: defaultDS        # 源數據源的key, 對應上面配置的srcDataSources中的值
destination: example            # cannal的instance或者MQ的topic
outerAdapterKey: oracle1        # adapter key, 對應上面配置outAdapters中的key
concurrent: true                # 是否按主鍵hase並行同步, 並行同步的表必須保證主鍵不會更改及主鍵不能為其他同步表的外鍵!!
dbMapping:
  database: mytest              # 源數據源的database/shcema
  table: user                   # 源數據源表名
  targetTable: mytest.tb_user   # 目標數據源的庫名.表名
  targetPk:                     # 主鍵映射
    id: id                      # 如果是復合主鍵可以換行映射多個
#  mapAll: true                 # 是否整表映射, 要求源表和目標表字段名一模一樣 (如果targetColumns也配置了映射,則以targetColumns配置為准)
  targetColumns:                # 字段映射, 格式: 目標表字段: 源表字段, 如果字段名一樣源表字段名可不填
    id:
    name:
    role_id:
    c_time:
    test1: 

導入的類型以目標表的元類型為准, 將自動轉換

4.3 啟動RDB數據同步

將目標庫的jdbc jar包放入lib文件夾, 這里放入ojdbc6.jar

啟動canal-adapter啟動器

bin/startup.sh

驗證

修改mysql mytest.user表的數據, 將會自動同步到Oracle的MYTEST.TB_USER表下面, 並會打出DML的log

五、ElasticSearch適配器

5.1 修改啟動器配置: application.yml

server:
  port: 8081
logging:
  level:
    com.alibaba.otter.canal.client.adapter.es: DEBUG
spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8
    default-property-inclusion: non_null

canal.conf:
  canalServerHost: 127.0.0.1:11111
  flatMessage: true
  srcDataSources:
    defaultDS:
      url: jdbc:mysql://127.0.0.1:3306/mytest?useUnicode=true
      username: root
      password: 121212
  canalInstances:
  - instance: example
    adapterGroups:
    - outAdapters:
      - name: es
        hosts: 127.0.0.1:9300               # es 集群地址, 逗號分隔
        properties:
          cluster.name: elasticsearch       # es cluster name

adapter將會自動加載 conf/es 下的所有.yml結尾的配置文件

5.2 適配器表映射文件

修改 conf/es/mytest_user.yml文件:

dataSourceKey: defaultDS        # 源數據源的key, 對應上面配置的srcDataSources中的值
destination: example            # cannal的instance或者MQ的topic
esMapping:
  _index: mytest_user           # es 的索引名稱
  _type: _doc                   # es 的doc名稱
  _id: _id                      # es 的_id, 如果不配置該項必須配置下面的pk項_id則會由es自動分配
#  pk: id                       # 如果不需要_id, 則需要指定一個屬性為主鍵屬性
  # sql映射
  sql: "select a.id as _id, a.name as _name, a.role_id as _role_id, b.role_name as _role_name,
        a.c_time as _c_time, c.labels as _labels from user a
        left join role b on b.id=a.role_id
        left join (select user_id, group_concat(label order by id desc separator ';') as labels from label
        group by user_id) c on c.user_id=a.id"
#  objFields:
#    _labels: array:;           # 數組或者對象屬性, array:; 代表以;字段里面是以;分隔的
#    _obj: obj:{"test":"123"}
  etlCondition: "where a.c_time>='{0}'"     # etl 的條件參數
  commitBatch: 3000                         # 提交批大小

sql映射說明:

sql支持多表關聯自由組合, 但是有一定的限制:

  1. 主表不能為子查詢語句
  2. 只能使用left outer join即最左表一定要是主表
  3. 關聯從表如果是子查詢不能有多張表
  4. 主sql中不能有where查詢條件(從表子查詢中可以有where條件但是不推薦, 可能會造成數據同步的不一致, 比如修改了where條件中的字段內容)
  5. 關聯條件只允許主外鍵的'='操作不能出現其他常量判斷比如: on a.role_id=b.id and b.statues=1
  6. 關聯條件必須要有一個字段出現在主查詢語句中比如: on a.role_id=b.id 其中的 a.role_id 或者 b.id 必須出現在主select語句中

Elastic Search的mapping 屬性與sql的查詢值將一一對應(不支持 select *), 比如: select a.id as _id, a.name, a.email as _email from user, 其中name將映射到es mapping的name field, _email將 映射到mapping的_email field, 這里以別名(如果有別名)作為最終的映射字段. 這里的_id可以填寫到配置文件的 _id: _id映射.

5.2.1.單表映射索引示例sql:

select a.id as _id, a.name, a.role_id, a.c_time from user a

該sql對應的es mapping示例:

{
    "mytest_user": {
        "mappings": {
            "_doc": {
                "properties": {
                    "name": {
                        "type": "text"
                    },
                    "role_id": {
                        "type": "long"
                    },
                    "c_time": {
                        "type": "date"
                    }
                }
            }
        }
    }
}

5.2.2.單表映射索引示例sql帶函數或運算操作:

select a.id as _id, concat(a.name,'_test') as name, a.role_id+10000 as role_id, a.c_time from user a

函數字段后必須跟上別名, 該sql對應的es mapping示例:

{
    "mytest_user": {
        "mappings": {
            "_doc": {
                "properties": {
                    "name": {
                        "type": "text"
                    },
                    "role_id": {
                        "type": "long"
                    },
                    "c_time": {
                        "type": "date"
                    }
                }
            }
        }
    }
}

5.2.3.多表映射(一對一, 多對一)索引示例sql:

select a.id as _id, a.name, a.role_id, b.role_name, a.c_time from user a 
left join role b on b.id = a.role_id

注:這里join操作只能是left outer join, 第一張表必須為主表!!

該sql對應的es mapping示例:

{
    "mytest_user": {
        "mappings": {
            "_doc": {
                "properties": {
                    "name": {
                        "type": "text"
                    },
                    "role_id": {
                        "type": "long"
                    },
                    "role_name": {
                        "type": "text"
                    },
                    "c_time": {
                        "type": "date"
                    }
                }
            }
        }
    }
}

5.2.4.多表映射(一對多)索引示例sql:

select a.id as _id, a.name, a.role_id, c.labels, a.c_time from user a 
left join (select user_id, group_concat(label order by id desc separator ';') as labels from label
        group by user_id) c on c.user_id=a.id

注:left join 后的子查詢只允許一張表, 即子查詢中不能再包含子查詢或者關聯!!

該sql對應的es mapping示例:

{
    "mytest_user": {
        "mappings": {
            "_doc": {
                "properties": {
                    "name": {
                        "type": "text"
                    },
                    "role_id": {
                        "type": "long"
                    },
                    "c_time": {
                        "type": "date"
                    },
                    "labels": {
                        "type": "text"
                    }
                }
            }
        }
    }
}

5.2.5.其它類型的sql示例:

  • geo type
select ... concat(IFNULL(a.latitude, 0), ',', IFNULL(a.longitude, 0)) AS location, ...
  • 復合主鍵
select concat(a.id,'_',b.type) as _id, ... from user a left join role b on b.id=a.role_id
  • 數組字段
select a.id as _id, a.name, a.role_id, c.labels, a.c_time from user a 
left join (select user_id, group_concat(label order by id desc separator ';') as labels from label
        group by user_id) c on c.user_id=a.id

配置中使用:

objFields:
  labels: array:;

5.3 啟動ES數據同步

啟動canal-adapter啟動器

bin/startup.sh

驗證

  1. 新增mysql mytest.user表的數據, 將會自動同步到es的mytest_user索引下面, 並會打出DML的log
  2. 修改mysql mytest.role表的role_name, 將會自動同步es的mytest_user索引中的role_name數據
  3. 新增或者修改mysql mytest.label表的label, 將會自動同步es的mytest_user索引中的labels數據


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM