使用嵌入式Debezium和SpringBoot捕獲更改資料事件(CDC) - Sohan Ganapathy
在處理資料或複製資料來源時,您可能已經聽說過術語更改資料捕獲(CDC)。顧名思義,“ CDC”是一種設計模式,可以持續識別並捕獲資料的增量更改。該模式用於跨實時資料庫到分析資料來源或只讀副本的實時資料複製。它還可以用於根據資料更改觸發事件,例如OutBox模式。
大多數現代資料庫透過事務日誌支援CDC 。事務日誌是對資料庫所做的所有更改的順序記錄,而實際資料包含在單獨的檔案中。
在這個部落格中,我想集中精力使用CDC常用的框架,並將其嵌入SpringBoot。
什麼是Debezium?
Debezium是為CDC構建的分散式平臺,它使用資料庫事務日誌並在行級別更改時建立事件流。偵聽這些事件的應用程式可以基於增量資料更改來執行所需的操作。
Debezium提供了一個聯結器庫,支援當今可用的各種資料庫。這些聯結器可以監視和記錄資料庫模式中的行級更改,然後將更改釋出到諸如Kafka的流服務上。
通常,將一個或多個聯結器部署到Kafka Connect 叢集中,並配置為監視資料庫並將資料更改事件釋出到Kafka。分散式Kafka Connect群集可提供所需的容錯能力和可伸縮性,從而確保所有已配置的聯結器始終處於執行狀態。
什麼是嵌入式Debezium?
不需要容錯和可靠性水平的應用程式,或者希望將執行整個平臺的成本降至最低的應用程式,可以在應用程式中執行Debezium聯結器。這是透過嵌入Debezium引擎並將聯結器配置為在應用程式中執行來完成的。在發生資料更改事件時,聯結器會將它們直接傳送到應用程式。
使用SpringBoot執行Debezium
我們有一個SpringBoot應用程式“ Student CDC Relay”,它執行嵌入式Debezium,並追加包含“ Student”表的Postgres資料庫的事務日誌。當在“Student”表上執行諸如插入/更新/刪除之類的資料庫操作時,在SpringBoot應用程式中配置的Debezium聯結器將在應用程式內呼叫一個方法。該方法對這些事件起作用,並在ElasticSearch上的Student索引中同步資料。
示例程式碼可在此處找到。
安裝所需工具
可以在下面的docker-compose檔案中安裝所有必需的工具。這將在埠5432上啟動Postgres資料庫,並在埠9200(HTTP)和9300(Transport)上啟動Elastic Search 。
version: "3.5" services: # Install postgres and setup the student database. postgres: container_name: postgres image: debezium/postgres ports: - 5432:5432 environment: - POSTGRES_DB=studentdb - POSTGRES_USER=user - POSTGRES_PASSWORD=password # Install Elasticsearch. elasticsearch: container_name: elasticsearch image: docker.elastic.co/elasticsearch/elasticsearch:6.8.0 environment: - discovery.type=single-node ports: - 9200:9200 - 9300:9300 |
我們使用映象debezium/postgres,因為它預先構建了邏輯解碼功能。這是一種機制,它允許提取已提交到事務日誌的更改,從而使CDC成為可能。可以在此處找到將外掛安裝到Postgres的文件。
瞭解程式碼
第一步是為debezium-embedded和定義Maven依賴項debezium-connector。該示例從Postgres讀取更改,因此我們使用Postgres聯結器。
<dependency> <groupId>io.debezium</groupId> <artifactId>debezium-embedded</artifactId> <version>${debezium.version}</version> </dependency> <dependency> <groupId>io.debezium</groupId> <artifactId>debezium-connector-postgres</artifactId> <version>${debezium.version}</version> </dependency> |
然後,我們配置聯結器,該聯結器偵聽Student表上的更改。我們使用PostgresConnector,對於connector.class這是由Debezium提供設定。這是追加資料庫的聯結器的Java類的名稱。
聯結器還具有一個重要的設定- offset.storage,它可以幫助應用程式從事務日誌中跟蹤已處理的數量。如果應用程式在處理過程中失敗,它可以從重新啟動後失敗的地方繼續讀取更改。有多種儲存偏移量的方法,但是在此示例中,我們使用類FileOffsetBackingStore將偏移量儲存在由定義的本地檔案中offset.storage.file.filename。聯結器會記錄檔案中的偏移量,對於它讀取的每個更改,Debezium引擎都會根據setting定期將偏移量重新整理到檔案中offset.flush.interval.ms。
聯結器的其他引數是容納Student表的Postgres資料庫屬性。
@Bean public io.debezium.config.Configuration studentConnector() { return io.debezium.config.Configuration.create() .with("connector.class", "io.debezium.connector.postgresql.PostgresConnector") .with("offset.storage", "org.apache.kafka.connect.storage.FileOffsetBackingStore") .with("offset.storage.file.filename", "/path/cdc/offset/student-offset.dat") .with("offset.flush.interval.ms", 60000) .with("name", "student-postgres-connector") .with("database.server.name", studentDBHost+"-"+studentDBName) .with("database.hostname", studentDBHost) .with("database.port", studentDBPort) .with("database.user", studentDBUserName) .with("database.password", studentDBPassword) .with("database.dbname", studentDBName) .with("table.whitelist", STUDENT_TABLE_NAME).build(); } |
設定嵌入式Debezium的最後更改是在應用程式啟動時啟動它。為此,我們使用類EmbeddedEngine,該類充當聯結器的包裝器並管理聯結器的生命週期。使用聯結器配置和為每個資料更改事件將呼叫的函式(在我們的示例中為method)建立引擎handleEvent()。
private CDCListener(Configuration studentConnector, StudentService studentService) { this.engine = EmbeddedEngine .create() .using(studentConnector) .notifying(this::handleEvent).build(); this.studentService = studentService; } |
在handleEvent()解析每個事件時,StudentService使用Spring Data JPA for Elasticsearch對發生的操作進行標識並呼叫,以在Elastic Search上執行建立/更新/刪除操作。
現在我們已經設定好了,EmbeddedEngine我們可以使用該Executor服務非同步啟動它了。
private final Executor executor = Executors.newSingleThreadExecutor(); ... @PostConstruct private void start() { this.executor.execute(engine); } @PreDestroy private void stop() { if (this.engine != null) { this.engine.stop(); } } |
看到實際的程式碼
一旦我們使用命令執行docker-compose檔案並使用命令docker-compose up -d啟動'Student CDC Relay' 啟動了所有必需的工具mvn spring-boot:run。我們可以透過執行以下指令碼來設定Student表:
CREATE TABLE public.student ( id integer NOT NULL, address character varying(255), email character varying(255), name character varying(255), CONSTRAINT student_pkey PRIMARY KEY (id) ); |
為了檢視執行中的程式碼,我們在剛建立的表上進行了資料更改。
將記錄插入到學生表中:
執行下面的SQL將記錄插入到Postgres的Student表中。
INSERT INTO STUDENT(ID, NAME, ADDRESS, EMAIL) VALUES('1','Jack','Dallas, TX','jack@gmail.com'); |
確認Elastic Search上資料已經更改:
$ curl -X GET http://localhost:9200/student/student/1?pretty=true { "_index" : "student", "_type" : "student", "_id" : "1", "_version" : 31, "_seq_no" : 30, "_primary_term" : 1, "found" : true, "_source" : { "id" : 1, "name" : "Jack", "address" : "Dallas, TX", "email" : "jack@gmail.com" } } |
更新:
UPDATE STUDENT SET EMAIL='jill@gmail.com', NAME='Jill' WHERE ID = 1; |
我們可以在Elastic Search上驗證資料已更改為“Jill”
$ curl -X GET http://localhost:9200/student/student/1?pretty=true { "_index" : "student", "_type" : "student", "_id" : "1", "_version" : 32, "_seq_no" : 31, "_primary_term" : 1, "found" : true, "_source" : { "id" : 1, "name" : "Jill", "address" : "Dallas, TX", "email" : "jill@gmail.com" } } |
最後的想法
這種方法確實非常簡單,只有很少的活動部件,但是在縮放方面受到更大的限制,並且對故障的容忍度也大大降低。
當CDC-Relay應用程式執行良好時,將完全處理一次 源記錄,但是在CDC-Relay應用程式重新啟動後,底層應用程式確實需要容忍接收重複事件。
我們可以透過在另一個埠上啟動“ Student CDC Relay”的另一個例項來測試圍繞縮放的限制,我們看到以下異常:
2019-11-20 12:33:17.901 ERROR 59453 --- [pool-2-thread-1] io.debezium.embedded.EmbeddedEngine : Error while trying to run connector class 'io.debezium.connector.postgresql.PostgresConnector' Caused by: org.postgresql.util.PSQLException: ERROR: replication slot "debezium" is active for PID <> at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2440) ~[postgresql-42.2.5.jar:42.2.5] at org.postgresql.core.v3.QueryExecutorImpl.processCopyResults(QueryExecutorImpl.java:1116) ~[postgresql-42.2.5.jar:42.2.5] at org.postgresql.core.v3.QueryExecutorImpl.startCopy(QueryExecutorImpl.java:842) ~[postgresql-42.2.5.jar:42.2.5] at org.postgresql.core.v3.replication.V3ReplicationProtocol.initializeReplication(V3ReplicationProtocol.java:58) ~[postgresql-42.2.5.jar:42.2.5] at org.postgresql.core.v3.replication.V3ReplicationProtocol.startLogical(V3ReplicationProtocol.java:42) ~[postgresql-42.2.5.jar:42.2.5] at org.postgresql.replication.fluent.ReplicationStreamBuilder$1.start(ReplicationStreamBuilder.java:38) ~[postgresql-42.2.5.jar:42.2.5] at org.postgresql.replication.fluent.logical.LogicalStreamBuilder.start(LogicalStreamBuilder.java:37) ~[postgresql-42.2.5.jar:42.2.5] |
如果您的應用程式需要所有訊息的至少一次傳送保證,最好將完整的分散式Debezium系統與Kafka-Connect一起使用。
相關文章
- 使用Spring Cloud Data Flow + CDC Debezium源實時實現變更資料捕獲 - SpringIOSpringCloud
- SQL Server 變更資料捕獲(CDC)SQLServer
- Oracle CDC 變更資料捕獲技術Oracle
- 資料抽取中的CDC(變化資料捕獲)方式
- zendesk/maxwell:MySQL的CDC資料更新捕獲者MySql
- 關於js事件冒泡和事件捕獲JS事件
- 理解js的事件冒泡和事件捕獲JS事件
- JavaScript事件捕獲冒泡與捕獲JavaScript事件
- 變更資料捕獲CDC幾種應用場景 - RTInsights
- 變更資料捕獲CDC的八個實際案例 - Dunith
- JavaScript 事件捕獲JavaScript事件
- 如何實現對 Oracle 的實時資料捕獲和效能調優|Flink CDC 專題Oracle
- 使用 Postgres、Debezium 和 Kafka 流式傳輸資料Kafka
- Debezium結合Kafka Connect實時捕獲MySQL變更事件寫入Elasticsearch實現搜尋流程KafkaMySql事件Elasticsearch
- 基於Apache Hudi和Debezium構建CDC入湖管道Apache
- 事件的捕獲、冒泡、委託事件
- javascript事件捕獲是什麼意思JavaScript事件
- Javascript中的事件冒泡與捕獲JavaScript事件
- JS中的事件順序(事件捕獲與冒泡)JS事件
- SpringBoot之全域性捕獲異常Spring Boot
- 使用捕獲 獲取身份證號的資訊
- [資料整合/資料同步] 基於資料庫增量日誌的資料同步方案 : Flink CDC/Debezium/DataX/Canal/Oracle Goldengate/Kettle/Sqoop資料庫OracleGoOOP
- Springboot非同步事件配置和使用Spring Boot非同步事件
- Spirit帶你徹底瞭解事件捕獲和冒泡機制事件
- 事件溯源模式:分離事件的發生和捕獲兩種不同時間 - verraes事件模式
- 如何捕獲html資料表格連結?HTML
- 資料更改事件的三種型別事件型別
- 大資料技術 - Debezium大資料
- sqlplus -prelim和oradebug捕獲資料庫hang住的詳細資訊SQL資料庫
- javascript捕獲組如何使用JavaScript
- Auto.js Pro 資料獲取 與 異常捕獲JS
- [Flink/CDC/資料整合] 資料增量整合方案:Flink CDC
- Debezium zookeeper kafka mysql資料處理KafkaMySql
- 使用 C# 捕獲程式輸出C#
- JS 使用try catch捕獲異常JS
- async和await的錯誤捕獲AI
- jQuery捕獲jQuery
- Netflix計劃於2020年開源的資料庫資料複製重器:DBLog,一個類似Oracle OGG的通用的變更資料捕獲CDC框架 - Netflix資料庫Oracle框架