canal入門Demo


關於canal具體的原理,以及應用場景,可以參考開發文檔:https://github.com/alibaba/canal

 

下面給出canal的入門Demo

(一)部署canal服務器

可以參考官方文檔的QuickStart:https://github.com/alibaba/canal/wiki/QuickStart

為了完整性,下面重復給出如何配置canal服務器

開啟mysql的binlog功能,並配置binlog模式為row

1. Windows環境下,是修改my.ini文件:

[mysqld]
log-bin=mysql-bin #添加這一行就ok
binlog-format=ROW #選擇row模式
server_id=1 #配置mysql replaction需要定義,不能和canal的slaveId重復

2. 在mysql中 配置canal數據庫管理用戶,配置相應權限(repication權限),運行mysql后依次運行這四條代碼:

1 CREATE USER canal IDENTIFIED BY 'canal';  
2 GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'canal'@'%';
3 -- GRANT ALL PRIVILEGES ON *.* TO 'canal'@'%' ;
4 FLUSH PRIVILEGES;

3. 下載好canal,修改配置 instance.properties:

#################################################
## mysql serverId
canal.instance.mysql.slaveId = 1234
 
# position info,需要改成自己的數據庫信息
canal.instance.master.address = 127.0.0.1:3306 
canal.instance.master.journal.name = 
canal.instance.master.position = 
canal.instance.master.timestamp = 
 
#canal.instance.standby.address = 
#canal.instance.standby.journal.name =
#canal.instance.standby.position = 
#canal.instance.standby.timestamp = 
 
# username/password,需要改成自己的數據庫信息
canal.instance.dbUsername = canal  
canal.instance.dbPassword = canal
canal.instance.defaultDatabaseName = canal_test
canal.instance.connectionCharset = UTF-8
 
# table regex
canal.instance.filter.regex = .*\\..*
 
#################################################

4. 啟動startup.bat,並且查看日志log:

如果日志中有記錄,證明canal服務器部署成功了。

 

(二)運行canal客戶端

運行canal客戶端代碼時,一定要先啟動canal服務器!!!

1. 建立實例maven工程:

   

  • 不選擇任何Maven模板

 

2. 添加pom依賴:

<dependency>
    <groupId>com.alibaba.otter</groupId>
    <artifactId>canal.client</artifactId>
    <version>1.0.12</version>
</dependency>

 

3. 更新依賴

4. canal客戶端代碼:

 1 import java.net.InetSocketAddress;
 2 import java.util.List;
 3 
 4 import com.alibaba.otter.canal.client.CanalConnector;
 5 import com.alibaba.otter.canal.protocol.Message;
 6 import com.alibaba.otter.canal.protocol.CanalEntry.Column;
 7 import com.alibaba.otter.canal.protocol.CanalEntry.Entry;
 8 import com.alibaba.otter.canal.protocol.CanalEntry.EntryType;
 9 import com.alibaba.otter.canal.protocol.CanalEntry.EventType;
10 import com.alibaba.otter.canal.protocol.CanalEntry.RowChange;
11 import com.alibaba.otter.canal.protocol.CanalEntry.RowData;
12 import com.alibaba.otter.canal.client.*;
13 
14 public class canal_client {
15 
16     public static void main(String args[]) {
17         // 創建鏈接
18         CanalConnector connector = CanalConnectors.newSingleConnector(new InetSocketAddress("127.0.0.1",
19                 11111), "example", "", "");
20         int batchSize = 1000;
21         int emptyCount = 0;
22         try {
23             connector.connect();
24             connector.subscribe(".*\\..*");
25             connector.rollback();
26             int totalEntryCount = 1200;
27             while (emptyCount < totalEntryCount) {
28                 Message message = connector.getWithoutAck(batchSize); // 獲取指定數量的數據
29                 long batchId = message.getId();
30                 int size = message.getEntries().size();
31                 if (batchId == -1 || size == 0) {
32                     emptyCount++;
33                     System.out.println("empty count : " + emptyCount);
34                     try {
35                         Thread.sleep(5000);
36                     } catch (InterruptedException e) {
37                         e.printStackTrace();
38                     }
39                 } else {
40                     emptyCount = 0;
41                     printEntry(message.getEntries());
42                 }
43                 connector.ack(batchId); // 提交確認
44             }
45             System.out.println("empty too many times, exit");
46         }catch (Exception e){
47             //connector.rollback(batchId); // 處理失敗, 回滾數據
48         }
49         finally {
50             connector.disconnect();
51         }
52     }
53 
54     private static void printEntry( List<Entry> entrys) {
55         for (Entry entry : entrys) {
56             if (entry.getEntryType() == EntryType.TRANSACTIONBEGIN || entry.getEntryType() == EntryType.TRANSACTIONEND) {
57                 continue;
58             }
59             RowChange rowChage = null;
60             try {
61                 rowChage = RowChange.parseFrom(entry.getStoreValue());
62             } catch (Exception e) {
63                 throw new RuntimeException("ERROR ## parser of eromanga-event has an error , data:" + entry.toString(), e);
64             }
65 
66             EventType eventType = rowChage.getEventType();
67             System.out.println(String.format("================> binlog[%s:%s] , name[%s,%s] , eventType : %s",
68                     entry.getHeader().getLogfileName(), entry.getHeader().getLogfileOffset(),
69                     entry.getHeader().getSchemaName(), entry.getHeader().getTableName(),
70                     eventType));
71             for (RowData rowData : rowChage.getRowDatasList()) {
72                 if (eventType == EventType.DELETE) {
73                     printColumn(rowData.getBeforeColumnsList());
74                 } else if (eventType == EventType.INSERT) {
75                     printColumn(rowData.getAfterColumnsList());
76                 } else {
77                     System.out.println("-------> before");
78                     printColumn(rowData.getBeforeColumnsList());
79                     System.out.println("-------> after");
80                     printColumn(rowData.getAfterColumnsList());
81                 }
82             }
83         }
84     }
85 
86     private static void printColumn( List<Column> columns) {
87         for (Column column : columns) {
88             System.out.println(column.getName() + " : " + column.getValue() + "    update=" + column.getUpdated());
89         }
90     }
91 }
View Code

 

5. 運行客戶端實例:

 

6. 觸發數據庫變更:

 

 

總結:參考網上的資料,運行這個canal的Demo,對canal的機制有一點了解;當MySQL將binary log發送給canal服務器,然后canal client從服務器獲取binary log,同時解析出來,尤其是解析的過程對於理解canal會更深刻一點。

建議運行的代碼的過程中打斷點調試處理!


免責聲明!

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



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