Canal 是阿里巴巴開源的一款基於 MySQL 資料庫的增量日誌訂閱和解析工具,主要用於實現資料的實時同步和流處理。
透過使用 Canal,應用程式可以實現對資料庫變更的監聽,並將變更的資料實時同步到其他系統,比如訊息佇列、快取系統等。
先記一下快取雪崩的問題,
快取雪崩是指在我們的系統中,大量的快取資料在同一時間內失效,導致大量的請求直接打到資料庫上,從而引發資料庫壓力過大甚至當機。
Canal 可以幫助實現資料庫和快取的實時同步,減少快取失效對資料庫的衝擊。但是,要徹底解決快取雪崩問題,還需要結合其他策略,例如設定不同的快取過期時間、使用熔斷限流機制、引入分散式鎖等。
下面開搞Canal,現在大部分用的springboot寫專案,這裡記錄的用springboot整合的canal依賴,
通用的那個依賴包試了一下,沒配置的太麻煩了,用法也不一樣,日了小狗,所以還是用整合包,少整點配置
學的時候網上csdn上釋出教程的人純屬nt。一大堆用通用包,然後使用的程式碼又是springboot下的,tm的找半天原因為什麼找不到那個實現類,就是tm的瞎jb寫教程
這裡前提:
你的springboot已經引入了mysql資料庫依賴,我這裡用的持久層是mybatisPlus。這部分就不記錄了
1.安裝
1.1裝Canal
下載地址:alibaba/canal: 阿里巴巴 MySQL binlog 增量訂閱&消費元件 (github.com)
我安裝的是1.1.4版本,安裝好解壓 執行start指令碼啟動一下就行
1.2 依賴
<dependency>
<groupId>top.javatool</groupId>
<artifactId>canal-spring-boot-starter</artifactId>
<version>1.2.1-RELEASE</version>
</dependency>
1.3 寫下配置
application.yml裡面,加上cancal的配置,
我只填寫這兩個,因為很多配置是預設的,安裝好後canal我沒動任何配置,所以如果單獨自己修改了canal的某個配置,那麼這裡就要自己去加上修改的東西
canal:
server: 127.0.0.1:11111 # Canal伺服器地址和埠
destination: example # Canal目的地名稱
記得連線mysql資料庫的其它配置自己加上去,我這裡就不寫了
1.4 mysql資料庫給許可權和開啟binlog功能
資料庫開啟一下binlog功能:
找到你的mysql配置檔案,加上這個配置:
log-bin=mysql-bin # 開啟 binlog
binlog-format=ROW # 選擇 ROW 模式
server_id=1 # 配置 MySQL replaction 需要定義,不要和 canal 的 slaveId 重複
就是我劃的這三行,在[mysqld]下面直接加上就行,然後重啟一下mysql
然後還有下一步,
mysql資料庫還要給一下許可權才可以讓canal接入進來,讀取mysql資料庫的binlog,才可以捕獲到增刪改事件。
mysql中直接執行一下:
create user canal@'%' IDENTIFIED by 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT,SUPER ON *.* TO 'canal'@'%' ;
FLUSH PRIVILEGES;
解釋:
-
CREATE USER canal@'%' IDENTIFIED BY 'canal';
:建立一個新使用者canal
,並設定密碼為canal
。'%'
表示該使用者可以從任何主機連線到MySQL伺服器。 -
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT, SUPER ON *.* TO 'canal'@'%';
:給canal
使用者授予一系列許可權,包括:SELECT
:允許使用者查詢資料庫。REPLICATION SLAVE
:允許使用者請求從伺服器的binlog。REPLICATION CLIENT
:允許使用者查詢二進位制日誌檔案的位置。SUPER
:允許使用者執行一些超級使用者級別的操作,例如獲取當前binlog檔案的名稱和位置。
-
FLUSH PRIVILEGES;
:重新整理許可權,使更改立即生效。
2.實戰
2.1 建立實體類
和資料庫的 user使用者表欄位 對應上
寫好表名
@Data
@AllArgsConstructor
@NoArgsConstructor
@Table(name ="user")
public class User {
@TableId(type = IdType.AUTO)
@Id
private Integer id;
private String name;
private String password;
}
2.2 建立監控器
@Component
@CanalTable(value = "user")
public class UserCanalListener implements EntryHandler<User> {
@Override
public void insert(User user) {
System.out.println("新增了一條資料:" + user);
}
@Override
public void update(User before, User after) {
System.out.println("資料修改前:" + before);
System.out.println("資料修改後:" + after);
}
@Override
public void delete(User user) {
// EntryHandler.super.delete(user);
System.out.println("刪除使用者user = " + user);
}
}
實現 EntryHandler<實體類>即可,
這裡的insert 對應的就是插入資料的操作,我這裡 觸發插入的操作後,就把 插入的資料列印出來
後面的 update就是更新,delete就是刪除。
手動在資料庫改一下資料,canal就會監控到事件,執行你的程式碼,可以觸發後修改redis資料庫,進行資料和快取的同步。 也可以自己寫其他邏輯,同步其它資料庫
2.3 效果
首先,現在的資料庫有兩條記錄,我演示把張三的 password 欄位改一下 ,改成8888888看一下
觸發修改事件後:
資料改變後,觸發了我們寫的監控事件。列印出了改變前後的資料。
3.其它
有人問為什麼控制檯一直列印:獲取訊息 : xxxx[id:1] ....
這個是canal在不斷的輪詢監控,包的位置是這個:top.javatool.canal.client.client.AbstractCanalClient
這個類下面的方法process()會不斷執行
this.log.info("獲取訊息 {}", message);
如果不想在控制檯一直看到它輸出,可以在application.yml裡面改一下
logging:
level:
root: WARN
# 針對特定包或類的日誌級別設定
t.j.c.client.client: ERROR
# 或者如果你想要關閉所有DEBUG級別的日誌,包括root
DEBUG: OFF
針對這個包,改一下輸出級別就行。
4.總結
ok。沒總結,很簡單,這樣就結束了。