用Apache Kafka轻松实现从Oracle到MongoDB的数据移动

596 阅读5分钟

用Apache Kafka轻松实现从Oracle到MongoDB的数据移动

在数据库领域,变化数据捕获功能已经存在了很多年。CDC使得监听数据库的变化成为可能,如插入、更新和删除数据,并在ETL、复制和数据库迁移等各种情况下将这些事件发送到其他数据库系统。通过利用Apache Kafka、Confluent Oracle CDC Connector和MongoDB Connector for Apache Kafka,你可以轻松地将数据库变化从Oracle流转到MongoDB。在这篇文章中,我们将把数据从Oracle传到MongoDB,为你提供一步一步的配置,以方便你重新使用、调整和探索功能。

”

在高层次上,我们将在一个独立的docker compose环境中配置上述参考图像,该环境由以下部分组成:

  • Oracle数据库
  • MongoDB
  • Apache Kafka
  • Confluent KSQL

这些容器将全部在本地网络桥接中运行,因此你可以在本地的Mac或PC上玩弄它们。请查看GitHub资源库,下载完整的例子。

准备Oracle Docker镜像

如果你有一个现有的Oracle数据库,从docker-compose文件中删除 "数据库 "部分。如果你还没有一个Oracle数据库,你可以从Docker Hub拉出Oracle数据库企业版。你需要接受Oracle的条款和条件,然后通过docker login ,然后docker pull store/oracle/database-enterprise:12.2.0.1-slim ,登录到你的docker账户,在本地下载镜像。

启动docker环境

docker-compose文件将启动以下内容:

  • Apache Kafka,包括Zookeeper、REST API、模式注册表、KSQL
  • Apache Kafka连接
  • Apache Kafka的MongoDB连接器
  • Confluent Oracle CDC连接器
  • 甲骨文数据库企业

完整的示例代码可以从GitHub仓库中获得。

要启动该环境,请确保你的Oracle环境已经准备好了,然后git克隆该repo并构建以下内容:

docker-compose up -d --build

一旦编译文件完成,你将需要配置你的Oracle环境,以便被Confluent CDC Connector使用。

第1步:连接到你的Oracle实例

如果你在docker环境中运行Oracle,你可以使用docker exec,如下所示:

docker exec -it oracle bash -c "source /home/oracle/.bashrc; sqlplus /nolog "

connect / as sysdba

第2步:为CDC连接器配置Oracle

首先,检查数据库是否处于存档日志模式:

select log_mode from v$database;

如果模式不是 "ARCHIVELOG",请执行以下操作:

SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE OPEN;

验证归档模式:

select log_mode from v$database

LOG_MODE现在应该是,"ARCHIVELOG"。

接下来,为所有的列启用补充日志记录

ALTER SESSION SET CONTAINER=cdb$root;
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;

下面应该在Oracle CDB上运行:

CREATE ROLE C##CDC_PRIVS;
GRANT CREATE SESSION,
EXECUTE_CATALOG_ROLE,
SELECT ANY TRANSACTION,
SELECT ANY DICTIONARY TO C##CDC_PRIVS;
GRANT SELECT ON SYSTEM.LOGMNR_COL$ TO C##CDC_PRIVS;
GRANT SELECT ON SYSTEM.LOGMNR_OBJ$ TO C##CDC_PRIVS;
GRANT SELECT ON SYSTEM.LOGMNR_USER$ TO C##CDC_PRIVS;
GRANT SELECT ON SYSTEM.LOGMNR_UID$ TO C##CDC_PRIVS;
 
CREATE USER C##myuser IDENTIFIED BY password CONTAINER=ALL;
GRANT C##CDC_PRIVS TO C##myuser CONTAINER=ALL;
ALTER USER C##myuser QUOTA UNLIMITED ON sysaux;
ALTER USER C##myuser SET CONTAINER_DATA = (CDB$ROOT, ORCLPDB1) CONTAINER=CURRENT;
 
ALTER SESSION SET CONTAINER=CDB$ROOT;
GRANT CREATE SESSION, ALTER SESSION, SET CONTAINER, LOGMINING, EXECUTE_CATALOG_ROLE TO C##myuser CONTAINER=ALL;
GRANT SELECT ON GV_$DATABASE TO C##myuser CONTAINER=ALL;
GRANT SELECT ON V_$LOGMNR_CONTENTS TO C##myuser CONTAINER=ALL;
GRANT SELECT ON GV_$ARCHIVED_LOG TO C##myuser CONTAINER=ALL;
GRANT CONNECT TO C##myuser CONTAINER=ALL;
GRANT CREATE TABLE TO C##myuser CONTAINER=ALL;
GRANT CREATE SEQUENCE TO C##myuser CONTAINER=ALL;
GRANT CREATE TRIGGER TO C##myuser CONTAINER=ALL;
 
ALTER SESSION SET CONTAINER=cdb$root;
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
 
GRANT FLASHBACK ANY TABLE TO C##myuser;
GRANT FLASHBACK ANY TABLE TO C##myuser container=all;

接下来,创建一些对象

CREATE TABLE C##MYUSER.emp
(
   i INTEGER GENERATED BY DEFAULT AS IDENTITY,
   name VARCHAR2(100),
   lastname VARCHAR2(100),
   PRIMARY KEY (i)
) tablespace sysaux;
  
insert into C##MYUSER.emp (name, lastname) values ('Bob', 'Perez');
insert into C##MYUSER.emp (name, lastname) values ('Jane','Revuelta');
insert into C##MYUSER.emp (name, lastname) values ('Mary','Kristmas');
insert into C##MYUSER.emp (name, lastname) values ('Alice','Cambio');
commit;

第3步:创建Kafka主题

打开一个新的终端/shell,按如下方式连接到你的kafka服务器:

docker exec -it broker /bin/bash

当连接后,创建Kafka主题:

kafka-topics --create --topic SimpleOracleCDC-ORCLCDB-redo-log \
--bootstrap-server broker:9092 --replication-factor 1 \
--partitions 1 --config cleanup.policy=delete \
--config retention.ms=120960000

第4步:配置Oracle CDC连接器

资源库中的oracle-cdc-source.json文件包含Confluent Oracle CDC连接器的配置。要配置只需执行:

curl -X POST -H "Content-Type: application/json" -d @oracle-cdc-source.json  http://localhost:8083/connectors

第5步:在Kafka中设置kSQL数据流

当Oracle CRUD事件到达Kafka主题时,我们将使用KSQL将这些事件流到一个新的主题中,供Apache Kafka的MongoDB连接器使用:

docker exec -it ksql-server bin/bash

ksql http://127.0.0.1:8088

输入以下命令:

CREATE STREAM CDCORACLE (I DECIMAL(20,0), NAME varchar, LASTNAME varchar, op_type VARCHAR) WITH ( kafka_topic='ORCLCDB-EMP', PARTITIONS=1, REPLICAS=1, value_format='AVRO');

CREATE STREAM WRITEOP AS
  SELECT CAST(I AS BIGINT) as "_id",  NAME ,  LASTNAME , OP_TYPE  from CDCORACLE WHERE OP_TYPE!='D' EMIT CHANGES;

CREATE STREAM DELETEOP AS
  SELECT CAST(I AS BIGINT) as "_id",  NAME ,  LASTNAME , OP_TYPE  from CDCORACLE WHERE OP_TYPE='D' EMIT CHANGES;

为了验证流的创建。

SHOW STREAMS。

这个命令将显示如下:

Stream Name | Kafka Topic | Format 
------------------------------------
 CDCORACLE   | ORCLCDB-EMP | AVRO   
 DELETEOP    | DELETEOP    | AVRO   
 WRITEOP     | WRITEOP     | AVRO   
 ------------------------------------

第6步:配置MongoDB Sink

下面是Apache Kafka的MongoDB连接器的配置:

{
  "name": "Oracle",
  "config": {
    "connector.class": "com.mongodb.kafka.connect.MongoSinkConnector",
    "topics": "WRITEOP",
    "connection.uri": "mongodb://mongo1",
    "writemodel.strategy": "com.mongodb.kafka.connect.sink.writemodel.strategy.UpdateOneBusinessKeyTimestampStrategy",
    "database": "kafka",
    "collection": "oracle",
    "document.id.strategy": "com.mongodb.kafka.connect.sink.processor.id.strategy.PartialValueStrategy",
    "document.id.strategy.overwrite.existing": "true",
    "document.id.strategy.partial.value.projection.type": "allowlist",
    "document.id.strategy.partial.value.projection.list": "_id",
    "errors.log.include.messages": true,
    "errors.deadletterqueue.context.headers.enable": true,
    "value.converter":"io.confluent.connect.avro.AvroConverter",
    "value.converter.schema.registry.url":"http://schema-registry:8081",
    "key.converter":"org.apache.kafka.connect.storage.StringConverter"

  }
}

在这个例子中,这个水槽进程从WRITEOP主题消耗记录,并将数据保存到MongoDB。写入模型,UpdateOneBusinessKeyTimestampStrategy,使用定义在PartialValueStrategy属性上的过滤器执行上移操作,在这个例子中,这个属性是"_id "字段。为了方便你,这个配置脚本写在资源库中的mongodb-sink.json文件中。要配置执行:

curl -X POST -H "Content-Type: application/json" -d @mongodb-sink.json  http://localhost:8083/connectors

删除事件被写在DELETEOP主题中,并通过以下水槽配置被汇入MongoDB:

{
  "name": "Oracle-Delete",
  "config": {
    "connector.class": "com.mongodb.kafka.connect.MongoSinkConnector",
    "topics": "DELETEOP",
    "connection.uri": "mongodb://mongo1”,
    "writemodel.strategy": "com.mongodb.kafka.connect.sink.writemodel.strategy.DeleteOneBusinessKeyStrategy",
    "database": "kafka",
    "collection": "oracle",
    "document.id.strategy": "com.mongodb.kafka.connect.sink.processor.id.strategy.PartialValueStrategy",
    "document.id.strategy.overwrite.existing": "true",
    "document.id.strategy.partial.value.projection.type": "allowlist",
    "document.id.strategy.partial.value.projection.list": "_id",
    "errors.log.include.messages": true,
    "errors.deadletterqueue.context.headers.enable": true,
    "value.converter":"io.confluent.connect.avro.AvroConverter",
    "value.converter.schema.registry.url":"http://schema-registry:8081"

  }
}
curl -X POST -H "Content-Type: application/json" -d @mongodb-sink-delete.json  http://localhost:8083/connectors

这个水槽流程使用DeleteOneBusinessKeyStrategy的写入策略。在这种配置中,水槽从DELETEOP主题中读取,并根据PartialValueStrategy属性上定义的过滤器删除MongoDB中的文档。在这个例子中,该过滤器是"_id "字段。

第7步:向Oracle写入数据

现在你的环境已经设置和配置好了,返回到Oracle数据库并插入以下数据:

insert into C##MYUSER.emp (name, lastname) values ('Juan','Soto');
insert into C##MYUSER.emp (name, lastname) values ('Robert','Walters');
insert into C##MYUSER.emp (name, lastname) values ('Ruben','Trigo');
commit;

接下来,通过访问MongoDB的shell来注意数据到达MongoDB的情况:

docker exec -it mongo1 /bin/mongo

插入的数据现在将在MongoDB中可用:

”

如果我们更新Oracle中的数据,例如

UPDATE C##MYUSER.emp SET name=’Rob’ WHERE name=’Robert’;
COMMIT;\

该文件将在MongoDB中被更新为。

{
        "_id" : NumberLong(11),
        "LASTNAME" : "Walters",
        "NAME" : "Rob",
        "OP_TYPE" : "U",
        "_insertedTS" : ISODate("2021-07-27T10:25:08.867Z"),
        "_modifiedTS" : ISODate("2021-07-27T10:25:08.867Z")
}

如果我们删除Oracle中的数据,例如

DELETE FROM C##MYUSER.emp WHERE name=’Rob’; COMMIT;.

带有name='Rob'的文档将不再出现在MongoDB中。

注意,从Oracle到MongoDB的传播可能需要几秒钟。

许多可能性

在这篇文章中,我们通过Apache Kafka和Confluent Oracle CDC Connector和MongoDB Connector for Apache Kafka进行了一个将数据从Oracle转移到MongoDB的基本设置。虽然这个例子相当简单,但你可以使用KSQL添加更复杂的转换,并在你的Kafka环境中集成其他数据源,使生产准备ETL或流媒体环境与最佳解决方案。