Flink CDC 使用实践以及遇到的问题

背景

最近公司在做一些业务上的架构调整,有一部分是数据从mysql采集到Starrocks,之前的一套方法是走 debeziumpuslarstarrocks,这一套下来比较需要配置很多东西,而且出现问题以后,需要修改很多配置,而且现阶段问题比较多,且采集的是所有线上的数据库,维护起来很费劲。
于是我们进行了采集的数据流调整,使用 Flink CDC这一套,这一套 是端到端的,且采用配置化的方式,支持schema的变更,无需再多一层中间存储层。

最终配置

关于flink cdc的使用配置可以参考Flink CDC 源码解析–整体流程,我能这里只贴出来我们最终使用的配置:

source:
  type: mysql
  name: Database mysql to Data warehouse
  hostname: xxxx
  port: 3306
  username: xxx
  password: xxx
  tables:   db1.table1
  server-id: 556401-556500
  scan.startup.mode: initial
  scan.snapshot.fetch.size: 8096
  scan.incremental.snapshot.chunk.size: 16192
  debezium.max.queue.size: 162580
  debezium.max.batch.size: 40960
  debezium.poll.interval.ms: 50
  scan.only.deserialize.captured.tables.changelog.enabled: true
  scan.parallel-deserialize-changelog.enabled: true
  heartbeat.interval: 5s
  scan.newly-added-table.enabled: true

sink:
  type: starrocks
  name: StarRocks Sink
  jdbc-url: xxx
  load-url: xxx
  username: xxx
  password: xxx
  sink.buffer-flush.interval-ms: 5000
  table.create.properties.replication_num: 3
  table.create.num-buckets: 3

route:
  - source-table: db1.\.*
    sink-table: db1.<>
    replace-symbol: <>
    description: route all tables to starrrocks

pipeline:
  name: Sync mysql Database to StarRocks
  parallelism: 1
  schema.change.behavior: EVOLVE

遇到的问题

  1. EventHeaderV4反序列化问题
    报错如下:

      Caused by: io.debezium.DebeziumException: Failed to deserialize data of EventHeaderV4{timestamp=1732257303000, eventType=WRITE_ROWS, serverId=28555270, headerLength=19, dataLength=320, nextPosition=383299196, flags=0}
      	at io.debezium.connector.mysql.MySqlStreamingChangeEventSource.wrap(MySqlStreamingChangeEventSource.java:1718)
      	... 5 more
      Caused by: com.github.shyiko.mysql.binlog.event.deserialization.EventDataDeserializationException: Failed to deserialize data of EventHeaderV4{timestamp=1732257303000, eventType=WRITE_ROWS, serverId=28555270, headerLength=19, dataLength=320, nextPosition=383299196, flags=0}
      	at com.github.shyiko.mysql.binlog.event.deserialization.EventDeserializer.deserializeEventData(EventDeserializer.java:358)
      	at com.github.shyiko.mysql.binlog.event.deserialization.EventDeserializer.nextEvent(EventDeserializer.java:252)
      	at io.debezium.connector.mysql.MySqlStreamingChangeEventSource$1.nextEvent(MySqlStreamingChangeEventSource.java:388)
      	at com.github.shyiko.mysql.binlog.BinaryLogClient.listenForEventPackets(BinaryLogClient.java:1187)
      	... 3 more
      Caused by: java.io.EOFException: Failed to read remaining 28 of 36 bytes from position 258280448. Block length: 183. Initial block length: 316.
      	at com.github.shyiko.mysql.binlog.io.ByteArrayInputStream.fill(ByteArrayInputStream.java:115)
      	at com.github.shyiko.mysql.binlog.io.ByteArrayInputStream.read(ByteArrayInputStream.java:105)
      	at io.debezium.connector.mysql.RowDeserializers.deserializeVarString(RowDeserializers.java:264)
      	at io.debezium.connector.mysql.RowDeserializers$WriteRowsDeserializer.deserializeVarString(RowDeserializers.java:192)
      	at com.github.shyiko.mysql.binlog.event.deserialization.AbstractRowsEventDataDeserializer.deserializeCell(AbstractRowsEventDataDeserializer.java:189)
      	at com.github.shyiko.mysql.binlog.event.deserialization.AbstractRowsEventDataDeserializer.deserializeRow(AbstractRowsEventDataDeserializer.java:143)
      	at com.github.shyiko.mysql.binlog.event.deserialization.WriteRowsEventDataDeserializer.deserializeRows(WriteRowsEventDataDeserializer.java:75)
      	at com.github.shyiko.mysql.binlog.event.deserialization.WriteRowsEventDataDeserializer.deserialize(WriteRowsEventDataDeserializer.java:65)
      	at com.github.shyiko.mysql.binlog.event.deserialization.WriteRowsEventDataDeserializer.deserialize(WriteRowsEventDataDeserializer.java:38)
      	at com.github.shyiko.mysql.binlog.event.deserialization.EventDeserializer.deserializeEventData(EventDeserializer.java:352)
      	... 6 more
    

    过段时间自己恢复
    这个现象比较诡异,过段时间就自己恢复了,目前怀疑的点:

    • mysql连接数和带宽问题
    • msyql服务端的配置问题,可以参考Flink CDC FAQ
      mysql> set global slave_net_timeout = 120; 
      mysql> set global thread_pool_idle_timeout = 120;
      
    • 作业反压导致,参考阿里云Flink
      execution.checkpointing.interval=10min
      execution.checkpointing.tolerable-failed-checkpoints=100
      debezium.connect.keep.alive.interval.ms = 40000
      
  2. Starrocks Be 内存受限

       java.lang.RuntimeException: com.starrocks.data.load.stream.exception.StreamLoadFailException: Transaction prepare failed, db: shoufuyou_fund, table: fund_common_repay_push, label: flink-4c6c8cfb-5116-4c38-a60e-a1b87cd6f2f2, 
       responseBody: {
           "Status": "MEM_LIMIT_EXCEEDED",
           "Message": "Memory of process exceed limit. QUERY Backend: 172.17.172.251, fragment: 9048ed6e-6ffb-04db-081b-a4966b179387 Used: 26469550752, Limit: 26316804096. Mem usage has exceed the limit of BE"
       }
       errorLog: null
       	at com.starrocks.data.load.stream.v2.StreamLoadManagerV2.AssertNotException(StreamLoadManagerV2.java:427)
       	at com.starrocks.data.load.stream.v2.StreamLoadManagerV2.write(StreamLoadManagerV2.java:252)
       	at com.starrocks.connector.flink.table.sink.v2.StarRocksWriter.write(StarRocksWriter.java:143)
       	at org.apache.flink.streaming.runtime.operators.sink.SinkWriterOperator.processElement(SinkWriterOperator.java:182)
       	at org.apache.flink.cdc.runtime.operators.sink.DataSinkWriterOperator.processElement(DataSinkWriterOperator.java:178)
       	at org.apache.flink.streaming.runtime.tasks.CopyingChainingOutput.pushToOperator(CopyingChainingOutput.java:75)
       	at org.apache.flink.streaming.runtime.tasks.CopyingChainingOutput.collect(CopyingChainingOutput.java:50)
       	at org.apache.flink.streaming.runtime.tasks.CopyingChainingOutput.collect(CopyingChainingOutput.java:29)
       	at org.apache.flink.streaming.api.operators.StreamMap.processElement(StreamMap.java:38)
       	at org.apache.flink.streaming.runtime.tasks.OneInputStreamTask$StreamTaskNetworkOutput.emitRecord(OneInputStreamTask.java:245)
       	at org.apache.flink.streaming.runtime.io.AbstractStreamTaskNetworkInput.processElement(AbstractStreamTaskNetworkInput.java:217)
       	at org.apache.flink.streaming.runtime.io.AbstractStreamTaskNetworkInput.emitNext(AbstractStreamTaskNetworkInput.java:169)
       	at org.apache.flink.streaming.runtime.io.StreamOneInputProcessor.processInput(StreamOneInputProcessor.java:68)
       	at org.apache.flink.streaming.runtime.tasks.StreamTask.processInput(StreamTask.java:616)
       	at org.apache.flink.streaming.runtime.tasks.mailbox.MailboxProcessor.runMailboxLoop(MailboxProcessor.java:231)
       	at org.apache.flink.streaming.runtime.tasks.StreamTask.runMailboxLoop(StreamTask.java:1071)
       	at org.apache.flink.streaming.runtime.tasks.StreamTask.invoke(StreamTask.java:1020)
       	at org.apache.flink.runtime.taskmanager.Task.runWithSystemExitMonitoring(Task.java:959)
       	at org.apache.flink.runtime.taskmanager.Task.restoreAndInvoke(Task.java:938)
       	at org.apache.flink.runtime.taskmanager.Task.doRun(Task.java:751)
       	at org.apache.flink.runtime.taskmanager.Task.run(Task.java:567)
       	at java.lang.Thread.run(Thread.java:879)
       Caused by: com.starrocks.data.load.stream.exception.StreamLoadFailException: Transaction prepare failed, db: shoufuyou_fund, table: fund_common_repay_push, label: flink-4c6c8cfb-5116-4c38-a60e-a1b87cd6f2f2, 
       responseBody: {
           "Status": "MEM_LIMIT_EXCEEDED",
           "Message": "Memory of process exceed limit. QUERY Backend: 172.17.172.251, fragment: 9048ed6e-6ffb-04db-081b-a4966b179387 Used: 26469550752, Limit: 26316804096. Mem usage has exceed the limit of BE"
       }
       errorLog: null
       	at com.starrocks.data.load.stream.TransactionStreamLoader.prepare(TransactionStreamLoader.java:221)
       	at com.starrocks.data.load.stream.v2.TransactionTableRegion.commit(TransactionTableRegion.java:247)
       	at com.starrocks.data.load.stream.v2.StreamLoadManagerV2.lambda$init$0(StreamLoadManagerV2.java:210)
       	... 1 more
    

    由于我们 Starrocks BE的内存是在 32GB,开启多个Flink CDC 任务,会导致CDC初始化的时候,写入BE的数据太多,从而BE内存不够,
    解决: 降低 写入Starrocks的并行读,不要太多CDC同时并行
    也可以参考Troubleshooting StarRocks memory hog issues

  3. JobManager Direct buffer memory不够

      java. lang.OutOfMemoryError: Direct buffer memory
         at lava.n10.B1ts.reserveMemory(B1ts.lava:/08 ~ 7:1.8.0 312.
         at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:123) ~[7:1.8.0_372]
         at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:311) ~[7:1.8.0_3721 
         at sun.nio.ch.Util.getTemporaryDirectBuffer(Util.java:247) ~[7:1.8.0_372]
         at sun.nio.ch.IOUtil.write(IOUtil.java:60) ~[7:1.8.0_372]
         at sun.nio.ch.FileChannelImpl.write(FileChannelImpl.java:234) ~[?:1.8.0_372]
         at java.nio.channels.Channels.writeFullyImpl(Channels.java:78) ~[?:1.8.0_372]
         at java.nio.channels.Channels$1.write(Channels.java:174) ~[7:1.8.0_372]
         at org.apache.flink.core.fs.OffsetAware0utputStream.write(0ffsetAware0utputStream.java:48) ~[ververica-connector-vvp-1.17-vvr-8.0.9-2-SNAPSHOT-jar-with-dependencies.jar:1.17-vvr-8.0.9-2-SNAPSHOT]
         at org.apache.flink.core.fs.RefCountedFileWithStream.write(RefCountedFileWithStream.java:54) ~[ververica-connector-vvp-1.17-vvr-8.0.9-2-SNAPSHOT-jar-with-dependencies. jar: 1.17-vvr-8.0.9-2-SNAPSHOT
         at org.apache.flink.core.fs.RefCountedBufferingFileStream.write(RefCountedBufferingFileStream.java:88) ~[ververica-connector-vvp-1.17-vvr-8.0.9-2-SNAPSHOT-jar-with-dependencies.jar:1.17-vvr-8.0.9-2-SNAPSHOT]
         at ora.aoache.flink.fs.osshadooo.writer.OSSRecoverableFsDataOutoutStream.write OSSRecoverableFsDataOutoutStream.1ava:130) ~?:?
         at org.apache.flink. runtime.state.filesystem.FsCheckpointMetadata0utputStream.write(FsCheckpointMetadata0utputStream.java:78) ~[flink-dist-1.17-vvr-8.0.9-2-SNAPSHOT. jar:1.17-vvr-8.0.9-2-SNAPSHOT]
         at java.io.Data0utputStream.write(DataOutputStream.java:107) ~[7:1.8.0_372]
         at java.io.Filter0utputStream.write(FilterOutputStream.java:97) ~[7:1.8.0_372]
         at org.apache.flink. runtime.checkpoint.metadata.MetadataV2V3SerializerBase.serializeStreamStateHandle(MetadataV2V3SerializerBase.java:703) ~[flink-dist-1.17-vvr-8.0.9-2-SNAPSHOT. jar:1.17-vvr-8.0.9-2-SNAPSHOT]
         at org.apache. flink.runtime.checkpoint.metadata.MetadataV3Serializer.serializeStreamStateHandle(MetadataV3Serializer.java:264) ~[flink-dist-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT] at org.apache.flink. runtime.checkpoint.metadata.MetadataV3Serializer.serialize0peratorState(MetadataV3Serializer.java:109) ~[flink-dist-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT]
         at org.apache. flink. runtime.checkpoint.metadata.MetadataV2V3SerializerBase.serializeMetadata(MetadataV2V3SerializerBase.java:153) ~[flink-dist-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT]
         at org.apache.flink. runtime.checkpoint.metadata.MetadataV3Serializer.serialize(MetadataV3Serializer.java:83) ~[flink-dist-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT] at org.apache.flink.runtime.checkpoint.metadata.MetadataV4Serializer.serialize(MetadataV4Serializer.java:56) ~[flink-dist-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT]|
         at org.apache. flink. runtime.checkpoint.Checkpoints.storeCheckpointMetadata(Checkpoints. java:102) ~[flink-dist-1.17-vvr-8.0.
    
    

    解决:
    增加配置:

      jobmanager.memory.off-heap.size: 512mb
    
  4. TaskManager jvm内存不够

      java.util.concurrent.TimeoutException: Heartbeat of TaskManager with id job-da2375f5-405b-4398-a568-eaba9711576d-taskmanager-1-34 timed out.
      	at org.apache.flink.runtime.jobmaster.JobMaster$TaskManagerHeartbeatListener.notifyHeartbeatTimeout(JobMaster.java:1714)
      	at org.apache.flink.runtime.heartbeat.DefaultHeartbeatMonitor.run(DefaultHeartbeatMonitor.java:158)
      	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
      	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      	at org.apache.flink.runtime.rpc.akka.AkkaRpcActor.lambda$handleRunAsync$4(AkkaRpcActor.java:453)
      	at org.apache.flink.runtime.concurrent.akka.ClassLoadingUtils.runWithContextClassLoader(ClassLoadingUtils.java:68)
      	at org.apache.flink.runtime.rpc.akka.AkkaRpcActor.handleRunAsync(AkkaRpcActor.java:453)
      	at org.apache.flink.runtime.rpc.akka.AkkaRpcActor.handleRpcMessage(AkkaRpcActor.java:218)
      	at org.apache.flink.runtime.rpc.akka.FencedAkkaRpcActor.handleRpcMessage(FencedAkkaRpcActor.java:84)
      	at org.apache.flink.runtime.rpc.akka.AkkaRpcActor.handleMessage(AkkaRpcActor.java:168)
      	at akka.japi.pf.UnitCaseStatement.apply(CaseStatements.scala:24)
      	at akka.japi.pf.UnitCaseStatement.apply(CaseStatements.scala:20)
      	at scala.PartialFunction.applyOrElse(PartialFunction.scala:127)
      	at scala.PartialFunction.applyOrElse$(PartialFunction.scala:126)
      	at akka.japi.pf.UnitCaseStatement.applyOrElse(CaseStatements.scala:20)
      	at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:175)
      	at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:176)
      	at scala.PartialFunction$OrElse.applyOrElse(PartialFunction.scala:176)
      	at akka.actor.Actor.aroundReceive(Actor.scala:537)
      	at akka.actor.Actor.aroundReceive$(Actor.scala:535)
      	at akka.actor.AbstractActor.aroundReceive(AbstractActor.scala:220)
      	at akka.actor.ActorCell.receiveMessage(ActorCell.scala:579)
      	at akka.actor.ActorCell.invoke(ActorCell.scala:547)
      	at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:270)
      	at akka.dispatch.Mailbox.run(Mailbox.scala:231)
      	at akka.dispatch.Mailbox.exec(Mailbox.scala:243)
      	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
      	at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
      	at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
      	at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:175)
      
    

    解决:
    在运行的过程中我们发现TaskManager的 taskmanager.memory.managed.size 内存使用一直为0,这是因为我们这里没有状态的存储,只是ETL,可以参考Flink TaskManager Memory Model
    在这里插入图片描述

    所以增加以下配置

      taskmanager.memory.managed.size: 256mb
      taskmanager.memory.process.size: 4096m
      table.exec.state.ttl: 1 m
    
  5. 读取mysql数据过慢

      java.lang.RuntimeException: One or more fetchers have encountered exception
      	at org.apache.flink.connector.base.source.reader.fetcher.SplitFetcherManager.checkErrors(SplitFetcherManager.java:261) ~[flink-connector-files-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT]
      	at org.apache.flink.connector.base.source.reader.SourceReaderBase.getNextFetch(SourceReaderBase.java:185) ~[flink-connector-files-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT]
      	at org.apache.flink.connector.base.source.reader.SourceReaderBase.pollNext(SourceReaderBase.java:144) ~[flink-connector-files-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT]
      	at org.apache.flink.streaming.api.operators.SourceOperator.pollNext(SourceOperator.java:779) ~[flink-dist-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT]
      	at org.apache.flink.streaming.api.operators.SourceOperator.emitNext(SourceOperator.java:457) ~[flink-dist-1.17-vvr-8.0.9-2-SNAPSHOT.
        ...
      Caused by: java.lang.RuntimeException: SplitFetcher thread 0 received unexpected exception while polling the records
      	at org.apache.flink.connector.base.source.reader.fetcher.SplitFetcher.runOnce(SplitFetcher.java:165) ~[flink-connector-files-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT]
      	at org.apache.flink.connector.base.source.reader.fetcher.SplitFetcher.run(SplitFetcher.java:114) ~[flink-connector-files-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT]
      	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_372]
      	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_372]
      	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_372]
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_372]
      	... 1 more
      Caused by: java.lang.IllegalStateException: The connector is trying to read binlog starting at Struct{version=1.9.8.Final,connector=mysql,name=mysql_binlog_source,ts_ms=1732052840471,db=,server_id=0,file=mysql-bin.051880,pos=347695811,row=0}, but this is no longer available on the server. Reconfigure the connector to use a snapshot when needed.
      	at org.apache.flink.cdc.connectors.mysql.debezium.task.context.StatefulTaskContext.loadStartingOffsetState(StatefulTaskContext.java:212) ~[?:?]
      	at org.apache.flink.cdc.connectors.mysql.debezium.task.context.StatefulTaskContext.configure(StatefulTaskContext.java:133) ~[?:?]
      	at org.apache.flink.cdc.connectors.mysql.debezium.reader.BinlogSplitReader.submitSplit(BinlogSplitReader.java:105) ~[?:?]
      	at org.apache.flink.cdc.connectors.mysql.debezium.reader.BinlogSplitReader.submitSplit(BinlogSplitReader.java:71) ~[?:?]
      	at org.apache.flink.cdc.connectors.mysql.source.reader.MySqlSplitReader.pollSplitRecords(MySqlSplitReader.java:119) ~[?:?]
      	at org.apache.flink.cdc.connectors.mysql.source.reader.MySqlSplitReader.fetch(MySqlSplitReader.java:90) ~[?:?]
      	at org.apache.flink.connector.base.source.reader.fetcher.FetchTask.run(FetchTask.java:58) ~[flink-connector-files-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT]
      	at org.apache.flink.connector.base.source.reader.fetcher.SplitFetcher.runOnce(SplitFetcher.java:162) ~[flink-connector-files-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT]
      	at org.apache.flink.connector.base.source.reader.fetcher.SplitFetcher.run(SplitFetcher.java:114) ~[flink-connector-files-1.17-vvr-8.0.9-2-SNAPSHOT.jar:1.17-vvr-8.0.9-2-SNAPSHOT]
      	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_372]
      	at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_372]
      	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[?:1.8.0_372]
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[?:1.8.0_372]
      	... 1 more
    

    解决:
    参考debezium connectors阿里云,增加如下参数:

    debezium.max.queue.size: 162580
    debezium.max.batch.size: 40960
    debezium.poll.interval.ms: 50
    scan.only.deserialize.captured.tables.changelog.enabled: true
    
  6. 增量读取过慢,导致binlog 已经没了
    参考阿里云,增加如下参数

     scan.parallel-deserialize-changelog.enabled: true
     scan.parallel-deserialize-changelog.handler.size: 4
     heartbeat.interval: 5s
    
  7. 建表不支持 PARTITION BY date_trunc(“week”,date_created)
    在建表中只会出现以下报错信息:

  Unsupported expr ‘date_trunc

可以查看 AnalyzerUtils的1626行:
在这里插入图片描述

唯品会在构建其万亿级实时数据仓库的过程中,充分利用了Flink CDC(Change Data Capture)技术,以实现高效、低延迟的数据处理和分析能力。Flink CDC是一种能够捕获数据库中数据变更的技术,它允许实时处理数据库中的数据变化,从而支持实时数据分析和业务决策。 ### 架构设计 唯品会的实时数据仓库架构设计充分考虑了高性能、稳定性与可扩展性。在这一架构中,Flink CDC作为关键组件之一,负责从源数据库中捕获数据变更,并将这些变更实时传输到下游的数据处理系统中。这种设计不仅减少了数据处理的延迟,还提高了系统的整体效率和可靠性。 具体来说,唯品会采用了Kubernetes(k8s)作为基础架构平台,利用其强大的容器编排能力来管理和调度Flink任务。通过Kubernetes,唯品会能够灵活地调整资源分配,确保在高负载情况下也能保持系统的稳定性和性能。此外,Kubernetes还提供了自动化的故障恢复机制,进一步增强了系统的可靠性和可用性[^1]。 ### 应用场景 在实际应用中,唯品会的实时数据仓库广泛应用于多个业务领域,包括但不限于: - **实时监控**:通过实时处理和分析用户行为数据,快速发现业务异常,及时采取措施。 - **个性化推荐**:基于用户的实时行为数据,提供更加精准的商品推荐,提升用户体验。 - **营销活动支持**:实时分析营销活动的效果,帮助业务团队快速调整策略,最大化活动收益。 - **风险控制**:实时监测交易和用户行为,有效识别潜在的风险点,保障平台安全。 ### 技术挑战与解决方案 在实施Flink CDC的过程中,唯品会面临了多项技术挑战,包括如何处理大规模数据流、如何保证数据的一致性和准确性、以及如何优化数据传输的性能等。为了解决这些问题,唯品会采取了一系列创新性的解决方案: - **数据一致性**:通过精确控制数据捕获和处理的流程,确保在整个数据生命周期中数据的一致性和准确性。 - **性能优化**:利用Flink的窗口机制和状态管理功能,优化数据处理逻辑,减少不必要的计算开销,提高处理效率。 - **资源管理**:借助Kubernetes的强大功能,动态调整资源分配,确保系统在面对突发流量时仍能保持良好的性能表现。 ### 示例代码 以下是一个简单的Flink CDC作业示例,用于从MySQL数据库中捕获数据变更并将其发送到Kafka主题中: ```java import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.table.api.bridge.java.StreamTableEnvironment; public class FlinkCDCExample { public static void main(String[] args) throws Exception { StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); env.setParallelism(1); // Set the parallelism to 1 for simplicity StreamTableEnvironment tEnv = StreamTableEnvironment.create(env); // Create a source table from MySQL using Flink CDC tEnv.executeSql( "CREATE TABLE MySQLTable (" + " id INT PRIMARY KEY," + " name STRING" + ") WITH (" + " 'connector' = 'mysql-cdc'," + " 'hostname' = 'localhost'," + " 'port' = '3306'," + " 'database-name' = 'testdb'," + " 'table-name' = 'users'," + " 'username' = 'flink'," + " 'password' = 'flink'" + ")" ); // Create a sink table in Kafka tEnv.executeSql( "CREATE TABLE KafkaTable (" + " id INT," + " name STRING" + ") WITH (" + " 'connector' = 'kafka'," + " 'topic' = 'user-changes'," + " 'properties.bootstrap.servers' = 'localhost:9092'," + " 'format' = 'json'" + ")" ); // Insert data from MySQL to Kafka tEnv.executeSql("INSERT INTO KafkaTable SELECT * FROM MySQLTable"); } } ``` 上述代码展示了如何创建一个Flink CDC作业,该作业从MySQL数据库中捕获数据变更,并将这些变更发送到Kafka主题中,以便后续的数据处理和分析。 ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值