SpringBoot整合Canal進行資料庫 快取同步

Hello霖發表於2024-03-31

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

SpringBoot整合Canal進行資料庫 快取同步

然後還有下一步,

mysql資料庫還要給一下許可權才可以讓canal接入進來,讀取mysql資料庫的binlog,才可以捕獲到增刪改事件。

mysql中直接執行一下:

create user canal@'%' IDENTIFIED by 'canal';
GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT,SUPER ON *.* TO 'canal'@'%' ;
FLUSH PRIVILEGES;

解釋:

  1. CREATE USER canal@'%' IDENTIFIED BY 'canal';:建立一個新使用者canal,並設定密碼為canal'%'表示該使用者可以從任何主機連線到MySQL伺服器。

  2. GRANT SELECT, REPLICATION SLAVE, REPLICATION CLIENT, SUPER ON *.* TO 'canal'@'%';:給canal使用者授予一系列許可權,包括:

    • SELECT:允許使用者查詢資料庫。
    • REPLICATION SLAVE:允許使用者請求從伺服器的binlog。
    • REPLICATION CLIENT:允許使用者查詢二進位制日誌檔案的位置。
    • SUPER:允許使用者執行一些超級使用者級別的操作,例如獲取當前binlog檔案的名稱和位置。
  3. 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看一下

SpringBoot整合Canal進行資料庫 快取同步

觸發修改事件後:

SpringBoot整合Canal進行資料庫 快取同步

  

資料改變後,觸發了我們寫的監控事件。列印出了改變前後的資料。

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。沒總結,很簡單,這樣就結束了。

相關文章