この記事では、Canal データ同期スキルを始めることができます~

ビデオチュートリアルポータ​​ル:

運河ミニマリストの紹介: 運河データ同期スキルをすぐに始めるための 1 時間~_哔哩哔哩_bilibili運河ミニマリスト入門: 運河データ同期スキルをすぐに始めるための 1 時間~ 合計 13 個のビデオ: 01. 授業前のチュートリアルと事前知識、02. Canal コンポーネントの理解、03. MySQL のマスター/スレーブ レプリケーション原理など。UP マスターのさらにエキサイティングなビデオについては、UP アカウントにご注目ください。https://www.bilibili.com/video/BV1Uc411P7XN/?spm_id_from=333.337.search-card.all.click

1. 事前知識のポイント

1.1 カナルの発音

よく読まれている記事: 運河

1.2 前提知識のポイント

  • MySQLの基本操作

  • Javaの基本

  • スプリングブーツ

2. 運河の紹介

2.1 歴史的背景

初期の頃、アリババは杭州と米国にコンピューター ルームを展開していましたが、コンピューター ルーム間の同期というビジネス要件がありました。最初の実装はビジネス トリガーに基づいていたため、あまり便利ではありませんでした。2010 年に段階的に置き換えられました。データベース ログ分析により、多数のデータベース増分サブスクリプションおよび消費操作が導き出されます。この文脈で出てきたのがCanalだった。

2014 年頃、大規模なプロモーション活動における MySQL データベースの同時読み取りと書き込みの問題を解決するために、Tmall Double イレブンが初めて導入されました。その後、Ali 内で広く使用および推進され、2017 年に正式にオープンソース化されました。

Github:https://github.com/alibaba/canal

 

2.2 定義

Canal コンポーネントは、MySQL データベースの増分ログ解析に基づくコンポーネントであり、増分データのサブスクリプションと消費を提供し、ダウンストリームのコンシューマー (Kafka、RocketMQ など) またはストレージ (Elasticsearch、HBase、等。)。

平易な言葉: Canal は MySQL データの変更を感知し、変更されたデータを解析し、変更されたデータを MQ に送信するか、他のデータベースに同期して、さらなるビジネス ロジックの処理を待ちます。

3. Canalの動作原理

3.1 MySQL のマスター/スレーブ レプリケーションの原則

 

  • MySQL マスターは、データの変更をバイナリ ログ (略して Binlog) に書き込みます。

  • MySQL スレーブはマスターのバイナリ ログをリレー ログ (リレー ログ) にコピーします。

  • MySQL スレーブはリレー ログ操作を再生して、変更されたデータを最新のデータに同期します。

3.2 MySQL のバイログログ

3.2.1 はじめに

MySQL の Binlog は MySQL の最も重要なログと言え、すべての DDL および DML ステートメントをイベントの形式で記録します。

Binlog ログの記録には時間がかかり、公式データでは 1% のパフォーマンスの低下が示されているため、デフォルトでは MySQL は Binlog を有効にしません。

有効にするかどうかは開発時の実際の状況によって異なります。

一般に、Binlog ログは次の 2 つのシナリオで有効になります。

  • MySQL マスター/スレーブ クラスターをデプロイする場合、スレーブへのデータ同期を容易にするためにマスター側で Binlog を有効にする必要があります。

  • データが復元され、MySQL Binlog ツールを使用してデータが復元されます。

3.2.1 ビンログの分類

MySQL Binlog には STATEMENT、MIXED、ROW の 3 つの形式があります。構成ファイルでは、次の構成を選択できます。

binlog_format=ステートメントを配置します。混合|

分類 導入 アドバンテージ 欠点がある
声明 ステートメント レベルでは、書き込み操作を実行するすべてのステートメントが記録され、ROW モードと比較してスペースが節約されますが、update tt set create_date=now() などのデータの不整合が発生する可能性があり、必要なデータは異なるものによって異なります。実行時間 スペースを節約する データの不整合が発生する可能性がある
行レベル。各操作後の各行レコードの変更を記録します。更新のSQL実行結果が10,000行で1文のみ保存される場合、行であれば10,000行の結果がここに保存されます。 データの絶対的な一貫性を維持します。SQLが何であっても、どの関数が参照されても、実行後の効果のみを記録するため 多くのスペースを占有する
混合 ステートメントのアップグレードです。たとえば、関数に UUID() が含まれる場合、AUTO_INCREMENT フィールドを含むテーブルが更新される場合、INSERT DELAYED ステートメントが実行される場合、UDF を使用する場合は、ROW の方法で処理されます。 ある程度の一貫性を維持しながらスペースを節約する まれに依然として不整合が発生するケースがいくつかあり、また、ステートメントと混合はバイナリログの監視が必要な状況では不便です。

上記の比較に基づいて、Canal は監視と分析を実行したいと考えており、行形式を選択することがより適切です。  

3.3 運河の動作原理

  • Canal は自身を MySQL スレーブ (スレーブ ライブラリ) として偽装し、ダンプ プロトコルを MySQL マスター (メイン ライブラリ) に送信します。

  • MySQL マスター (メイン ライブラリ) がダンプ リクエストを受信し、バイナリ ログをスレーブ (つまり運河) にプッシュし始めます。

  • Canal は Binlog ログを受信して​​解析し、変更されたデータを取得して、後続のロジックを実行します

 

4. 運河応用シナリオ

4.1 データの同期

Canal は、ユーザーが MySQL データを Elasticsearch、Redis、その他のデータ ストレージ メディアにリアルタイムで同期するなど、さまざまなデータ同期操作を実行できるように支援します。

4.2 データベースのリアルタイム監視

Canal は MySQL の更新操作をリアルタイムで監視し、機密データの変更があった場合に関係者に通知できます。

4.3 データ分析とマイニング

Canal は、MySQL 増分データを Kafka などのメッセージ キューにポストして、データ分析とマイニングのためのデータ ソースを提供できます。

 

4.4 データベースのバックアップ

Canal は、MySQL マスター データベース上のデータ増分ログをスタンバイ データベースにコピーして、データベースのバックアップを実現できます。

 

4.5 データ統合

Canal は、複数の MySQL データベースからのデータを統合して、より効率的で信頼性の高いデータ処理ソリューションを提供できます。

4.6 データベースの移行

Canal は、MySQL データベースのバージョン アップグレードとデータ移行タスクの完了を支援します。

 

5、MySQLの準備

5.1 データベースの作成

新しいライブラリ: canal-demo

 

5.2 テーブルの作成

ユーザーテーブル

CREATE TABLE `user` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;

5.3 構成ファイルを変更して Binlog サポートを有効にする

mysql の設定ファイルを変更します。名前はmy.iniです。

server-id=1
log-bin=C:/ProgramData/MySQL/MySQL Server 8.0/binlogs/mysql-bin.log
binlog_format=row
binlog-do-db=canal-demo

server-id: mysql インスタンス ID。クラスタリング時にインスタンスを区別するために使用されます。

lob-bin: binlog ログ ファイル名

binlog_format: binlog ログ データの保存形式

binlog-do-db: binlog ログ データベースを有効にするように指定します。

注: 通常、同期するデータベースは状況に応じて指定されますが、設定されていない場合は、すべてのデータベースで Binlog が有効になっていることを意味します。

5.4 Binlog が有効になっていることを確認する

MySQL サービスを再起動し、Binlog ログを表示します。

方法 1:

show  VARIABLES like 'log_bin'

 

方法 2:

指定したディレクトリを入力します。

insert into user(name, age) values('dafei', 18);
insert into user(name, age) values('dafei', 18);
insert into user(name, age) values('dafei', 18);

 

 

6. 運河の設置と構成

6.1 ダウンロード

アドレス:リリース · alibaba/canal · GitHub

解凍するだけです。

6.2 構成

6.2.1 canal.propertiesの設定を変更する

canal.port = 11111
# tcp, kafka, rocketMQ, rabbitMQ, pulsarMQ
canal.serverMode = tcp

canal.destinations = example

canal.port: デフォルトのポート 11111

canal.serverMode: サービス モード、tcp は入力クライアントを意味し、xxMQ はさまざまなメッセージ ミドルウェアへの出力を意味します

canal.destinations: Canal は複数の MySQL データベースからデータを収集でき、各 MySQL データベースには独立した構成ファイル コントロールがあります。特定の構成ルール: conf/ ディレクトリの下に、フォルダーを使用して配置します。フォルダー名は MySQL インスタンスを表します。canal.destinations は、データを監視する必要があるデータベースを構成するために使用されます。複数の場合は分けて使用します

6.2.2 MySQLインスタンス構成ファイルinstance.propertiesの変更

設定/ディレクトリ

canal.instance.mysql.slaveId=20

# position info
canal.instance.master.address=127.0.0.1:3306

# username/password
canal.instance.dbUsername=root
canal.instance.dbPassword=admin

canal.instance.mysql.slaveId: canal スレーブステージ ID を使用します

canal.instance.master.address: データベース IP ポート

canal.instance.dbUsername: mysql アカウントに接続します

canal.instance.dbPassword: mysql に接続するためのパスワード

6.3 スタート

ダブルクリックして開始します

 

7. 運河プログラミング

7.1 ハローワールド

1>プロジェクトの作成: canal-hello

2> 関連する依存関係をインポートする

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

3> テストコードを書く

package com.langfeiyes.hello;

import com.alibaba.otter.canal.client.CanalConnector;
import com.alibaba.otter.canal.client.CanalConnectors;
import com.alibaba.otter.canal.protocol.CanalEntry;
import com.alibaba.otter.canal.protocol.Message;
import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;

import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CanalDemo {

    public static void main(String[] args) throws InvalidProtocolBufferException {
        //1.获取 canal 连接对象
        CanalConnector canalConnector = CanalConnectors.newSingleConnector(new InetSocketAddress("localhost", 11111), "example", "", "");
        while (true) {
            //2.获取连接
            canalConnector.connect();
            //3.指定要监控的数据库
            canalConnector.subscribe("canal-demo.*");
            //4.获取 Message
            Message message = canalConnector.get(100);
            List<CanalEntry.Entry> entries = message.getEntries();
            if (entries.size() <= 0) {
                System.out.println("没有数据,休息一会");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                for (CanalEntry.Entry entry : entries) {
                    // 获取表名
                    String tableName = entry.getHeader().getTableName();
                    //  Entry 类型
                    CanalEntry.EntryType entryType = entry.getEntryType();
                    //  判断 entryType 是否为 ROWDATA
                    if (CanalEntry.EntryType.ROWDATA.equals(entryType)) {
                        //  序列化数据
                        ByteString storeValue = entry.getStoreValue();
                        //  反序列化
                        CanalEntry.RowChange rowChange = CanalEntry.RowChange.parseFrom(storeValue);
                        // 获取事件类型
                        CanalEntry.EventType eventType = rowChange.getEventType();
                        // 获取具体的数据
                        List<CanalEntry.RowData> rowDatasList = rowChange.getRowDatasList();
                        // 遍历并打印数据
                        for (CanalEntry.RowData rowData : rowDatasList) {
                            List<CanalEntry.Column> beforeColumnsList = rowData.getBeforeColumnsList();
                            Map<String, Object> bMap = new HashMap<>();
                            for (CanalEntry.Column column : beforeColumnsList) {
                                bMap.put(column.getName(), column.getValue());
                            }
                            Map<String, Object> afMap = new HashMap<>();
                            List<CanalEntry.Column> afterColumnsList = rowData.getAfterColumnsList();
                            for (CanalEntry.Column column : afterColumnsList) {
                                afMap.put(column.getName(), column.getValue());
                            }
                            System.out.println("表名:" + tableName + ",操作类型:" + eventType);
                            System.out.println("改前:" + bMap );
                            System.out.println("改后:" + afMap );
                        }
                    }
                }
            }
        }
    }
}

4> テスト

canal-demo ライブラリのユーザー テーブルに対して DML 操作を実行し、出力された値を観察します。

Canal API システム分析

 

7.2 SpringBoot の統合

1>プロジェクトの作成: canal-sb-demo

2> 関連する依存関係をインポートする

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-parent</artifactId>
    <version>2.7.11</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency>
        <groupId>top.javatool</groupId>
        <artifactId>canal-spring-boot-starter</artifactId>
        <version>1.2.6-RELEASE</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.12</version>
    </dependency>
    <dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java</artifactId>
        <version>3.21.4</version>
    </dependency>
</dependencies>

 3>設定ファイル

canal:
  server: 127.0.0.1:11111 #canal 默认端口11111
  destination: example
spring:
  application:
    name: canal-sb-demo
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/canal-demo?useUnicode=true&characterEncoding=utf-8&serverTimezone=UTC&useSSL=false
    username: root
    password: admin

4> エンティティオブジェクト

package com.langfeiyes.sb.domain;

public class User {
    private Long id;
    private String name;
    private Integer age;

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

}

5>監視処理クラス

package com.langfeiyes.sb.handler;

import com.langfeiyes.sb.domain.User;
import org.springframework.stereotype.Component;
import top.javatool.canal.client.annotation.CanalTable;
import top.javatool.canal.client.handler.EntryHandler;

@Component
@CanalTable(value = "user")
public class UserHandler implements EntryHandler<User> {
 
    @Override
    public void insert(User user) {
        System.err.println("添加:" + user);
    }
 
    @Override
    public void update(User before, User after) {
        System.err.println("改前:" + before);
        System.err.println("改后:" + after);

    }
    @Override
    public void delete(User user) {
        System.err.println("删除:" + user);
    }
}

6>授業を開始する

@SpringBootApplication
public class App {
    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
    }
}

7> テスト

  • まず運河サーバーを起動します

  • プロジェクトを再開する

  • ユーザーテーブルを変更する

  • 観測結果

8、同じ種類のテクノロジー

タイプ 1: ログ解析に基づくデータ同期コンポーネント

このタイプのコンポーネントは、主にデータベースのBinlog (MySQL) や Redo Log (Oracle) などのログ ファイルを解析することでデータベースの追加、削除、変更の操作を取得し、これらの操作を記録します。次に、これらの操作記録をデータ同期の目的で別のデータベースに転送できます。このようなコンポーネントの代表的な製品としては、AliのオープンソースのCanalやTencent CloudのDBSyncなどが挙げられます。

タイプ 2: ETL ベースのデータ同期コンポーネント

ETL は Extract-Transform-Load であり、ソース システムからデータを抽出し、データを変換し、最後にターゲット システムにロードすることを指します。このようなコンポーネントは通常、複雑なデータ変換ルールとデータ マッピング関係を記述する必要があり、頻繁なデータ構造の変更、大量のデータ、および複数のデータ ソースを伴うシナリオに適しています。代表的な製品としては、Alibaba CloudのDataWorksInformatica PowerCenterなどが挙げられます。

タイプ 3: CDC ベースのデータ同期コンポーネント

CDC (Change Data Capture) は変更データ キャプチャであり、データベース内のデータ変更をリアルタイムまたは準リアルタイムでキャプチャし、別のデータベースに送信できるデータ同期テクノロジです。CDC技術はデータベースのトランザクションログやREDOログを基に実装されており、低遅延で高性能なデータ同期を実現します。CDC コンポーネントの代表的な製品としては、Oracle GoldenGate、IBM Infosphere Data Replicationなどが挙げられます。

タイプ 4: メッセージ キューに基づくデータ同期コンポーネント

このようなコンポーネントは通常、データベース内で発生する変更操作をデータ構造に抽象化し、メッセージ キューを介して処理するために他のシステムに公開して、データの非同期送信と分離を実現します。代表的な製品としては、Apache Kafka、RabbitMQなどがあります。

9、Canal の面接でよくある質問

Q:カナルとは何ですか?特徴は何ですか?

回答: Canal は、Alibaba によってオープンソース化されている Netty をベースにした分散型、高性能、信頼性の高いメッセージ キューであり、リアルタイム データ同期およびデータ配布シナリオで幅広いアプリケーションを備えています。Canal には次の機能があります: MySQL、Oracle、その他のデータベースのログ解析とサブスクリプションをサポート、Kafka、RocketMQ、ActiveMQ などの複数のデータ出力方法をサポート、データ フィルタリングと形式変換をサポート、低レイテンシなどの優れた機能を備えています。高い信頼性とパフォーマンス。

Q: カナルはどのように機能しますか?

回答: Canal は主に、データベースの binlog ログを解析することによってデータベースの追加、削除、および変更操作を取得し、これらの変更イベントを下流のコンシューマーに送信します。Canal のコア コンポーネントには、クライアントとサーバーの 2 つの部分が含まれます。クライアントは、データベースへの接続、ログ解析の開始、解析されたデータのサーバーへの送信を担当します。サーバーは、クライアントから送信されたデータの受信と、ファイルのフィルタリングと配布を担当します。データ。Canal は、Kafka、RocketMQ、ActiveMQ などのさまざまなデータ エクスポーターもサポートしており、解析されたデータをさまざまなメッセージ キューに送信して、さらなる処理や分析を行うことができます。

Q: カナルの長所と短所は何ですか?

回答: Canal の主な利点には、高性能、分散型、優れた信頼性、データ フィルタリングと変換のサポート、およびクロスデータベース タイプ (MySQL、Oracle など) が含まれます。欠点としては、使いにくい、データベースのログに一定の影響がある、データのバックトラッキングがサポートされていない(つまり、履歴データを取得できない)などが挙げられます。

Q: Canal はビジネスにおいてどのような応用シナリオを考えていますか?

A: Canal は主にリアルタイム データ同期とデータ配布シナリオで使用されます。一般的なアプリケーション シナリオには、データ バックアップと災害復旧、増分データ抽出と同期、リアルタイム データ分析、オンライン データ移行などが含まれます。特にインターネットビッグデータのシナリオにおいて、Canal はさまざまなデータ処理タスクのための重要なツールの 1 つとなっています。

おすすめ

転載: blog.csdn.net/langfeiyes/article/details/130711899