如何從MySQL中將變化的事件資料釋出到Kafka?

banq發表於2018-11-26

如何使用Debezium向Kafka提交MySQL的更改資料事件? CDC(變更資料捕獲)是將OLTP資料庫系統與其他系統(如資料倉儲,快取,Spark或Hadoop)互連的最佳方式之一。

Debezium是由Red Hat開發的一個開源專案,旨在透過允許您從各種資料庫系統(例如MySQL,PostgreSQL,MongoDB)中提取更改並將其推送到Apache Kafka來簡化此過程。
在本文中,我們將瞭解如何使用Debezium從MySQL二進位制日誌中提取事件。

首先,您需要一個特定於資料庫的Debezium聯結器才能提取重做日誌(例如Oracle,MySQL)或預寫日誌(例如PostgreSQL)。
您還需要執行Kafka,以便可以推送提取的日誌事件並使其可用於企業系統中的其他服務。Debezium不需要Apache ZooKeeper,但Kafka需要它,因為它依賴於ZK的分散式共識以及線性化保證。

必須執行以下Docker容器安裝Debezium:


> docker run -it --name zookeeper -p 2181:2181 -p 2888:2888 -p 3888:3888 debezium/zookeeper:0.5

> docker run -it --name kafka -p 9092:9092 --link zookeeper:zookeeper debezium/kafka:0.5

> docker run -it --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=debezium -e MYSQL_USER=mysqluser -e MYSQL_PASSWORD=mysqlpw debezium/example-mysql:0.5

> docker run -it --name kafka-connect -p 8083:8083 -e GROUP_ID=1 -e CONFIG_STORAGE_TOPIC=my_connect_configs -e OFFSET_STORAGE_TOPIC=my_connect_offsets --link zookeeper:zookeeper --link kafka:kafka --link mysql:mysql debezium/connect:0.5

> docker run -it --name kafka-watcher --link zookeeper:zookeeper debezium/kafka:0.5 watch-topic -a -k dbserver1.inventory.customers


使用Docker列出容器:
docker ps -a

使用bash,您需要建立一個新聯結器:

curl -i -X POST -H "Accept:application/json" -H "Content-Type:application/json" localhost:8083/connectors/ -d '{ "name": "inventory-connector", "config": { "connector.class": "io.debezium.connector.mysql.MySqlConnector", "tasks.max": "1", "database.hostname": "mysql", "database.port": "3306", "database.user": "debezium", "database.password": "dbz", "database.server.id": "184054", "database.server.name": "dbserver1", "database.whitelist": "inventory", "database.history.kafka.bootstrap.servers": "kafka:9092", "database.history.kafka.topic": "dbhistory.inventory" } }'



kafka-watcher是以互動模式啟動的,這樣我們就可以在控制檯中看到Debezium捕獲的CDC日誌事件。

測試
現在,如果我們使用root使用者和debezium密碼連線到MySQL Docker容器,我們可以發出各種SQL語句並檢查kafka-watcher容器控制檯輸出。
插入新customer行時:

INSERT INTO `inventory`.`customers`
(
    `first_name`,
    `last_name`,
    `email`)
VALUES
(
    'Vlad',
    'Mihalcea',
    'vlad@acme.org'
)


在kafka-watcher,我們現在可以找到以下JSON條目:

{  
   "payload":{  
      "before":null,
      "after":{  
         "id":1005,
         "first_name":"Vlad",
         "last_name":"Mihalcea",
         "email":"vlad@acme.org"
      },
      "source":{  
         "name":"dbserver1",
         "server_id":223344,
         "ts_sec":1500369632,
         "gtid":null,
         "file":"mysql-bin.000003",
         "pos":364,
         "row":0,
         "snapshot":null,
         "thread":13,
         "db":"inventory",
         "table":"customers"
      },
      "op":"c",
      "ts_ms":1500369632095
   }
}

當after物件顯示新插入的值時,before是null,op屬性值是c,這意味著它是一個CREATE事件。

更新customer行時:

UPDATE `inventory`.`customers`
SET
    `email` = 'vlad.mihalcea@acme.org'
WHERE
    `id` = 1005



我們現在可以找到以下日誌事件:

{ 
    "payload":{  
      "before":{  
         "id":1005,
         "first_name":"Vlad",
         "last_name":"Mihalcea",
         "email":"vlad@acme.org"
      },
      "after":{  
         "id":1005,
         "first_name":"Vlad",
         "last_name":"Mihalcea",
         "email":"vlad.mihalcea@acme.org"
      },
      "source":{  
         "name":"dbserver1",
         "server_id":223344,
         "ts_sec":1500369929,
         "gtid":null,
         "file":"mysql-bin.000003",
         "pos":673,
         "row":0,
         "snapshot":null,
         "thread":13,
         "db":"inventory",
         "table":"customers"
      },
      "op":"u",
      "ts_ms":1500369929464
   }
}


發出DELETE語句時:

DELETE FROM `inventory`.`customers`
WHERE id = 1005;



kafka-connectDocker容器正在記錄以下事件:

{ 
    "payload":{  
      "before":{  
         "id":1005,
         "first_name":"Vlad",
         "last_name":"Mihalcea",
         "email":"vlad.mihalcea@acme.org"
      },
      "after":null,
      "source":{  
         "name":"dbserver1",
         "server_id":223344,
         "ts_sec":1500370394,
         "gtid":null,
         "file":"mysql-bin.000003",
         "pos":1025,
         "row":0,
         "snapshot":null,
         "thread":13,
         "db":"inventory",
         "table":"customers"
      },
      "op":"d",
      "ts_ms":1500370394589
   }
}

op屬性值d,這意味著我們有一個刪除日誌事件,after物件現在是null。before物件是在它被刪除之前捕獲的資料庫行狀態。

相關文章