【FLINKCDC】运行时经常server-id冲突报错?一招实现自动化!

前言

最近大批量flink-cdc任务运行遇到一个报错,加班的罪恶源头~server-id异常报错
server-id异常报错

Caused by: io.debezium.DebeziumException: 
    A slave with the same server_uuid/server_id as this slave has connected to the master; 
    the first event 'binlog.000002' at 1136, the last event read from './binlog.000002' at 1431, the last byte read from './binlog.000002' at 1431. 
    Error code: 1236; SQLSTATE: HY000.  at io.debezium.connector.mysql.MySqlStreamingChangeEventSource.wrap(MySqlStreamingChangeEventSource.java:1146)  
    ... 5 more
Caused by: com.github.shyiko.mysql.binlog.network.ServerException: 
    A slave with the same server_uuid/server_id as this slave has connected to the master; 
    the first event 'binlog.000002' at 1136, the last event read from './binlog.000002' at 1431, 
    the last byte read from './binlog.000002' at 1431.  
    at com.github.shyiko.mysql.binlog.BinaryLogClient.listenForEventPackets(BinaryLogClient.java:937)  
    ... 3 more

报错原因

该报错是同一个库(相同实例)同步多个表时,启动了多个flink-cdc任务时出现的。
经排查造成的原因是:
在这里插入图片描述

来自:阿里云开发者社区 chengfengpolang

一开始看到这个解释还是一脸懵的,配置mysql binlog的时候有印象确实设置过server-id = 1,难道是启动两个相同的mysql实例的flink-cdc任务时如果都用相同的server id会导致这类冲突报错?带着这个疑问我寻找了一些资料…

自从flink cdc贡献到apache后,有些资料在旧官网已经看不到了,不过在新官网中找到了server-id的一些相关配置。
在这里插入图片描述

深入细节

于是打开flink-cdc-connector源码一探究竟

MysqlSource createReader -> MysqlSourceConfigFactory

在这里插入图片描述

在源码注释里面也是很清晰说明了:这个server-id如果不设置的话默认是从5400-6400中随机分配一个数字,建议用户设置一个具体的值;同时也说了如果没开启参数scan.incremental.snapshot.enabled,则只用指定一个值,如果开启了该参数,则需要指定一个范围并且不能小于source的并行度。

这里可以对这个参数做一些解释,在flink-cdc 2.x版本引入了一个重要特性之一:增量快照读取机制。

这种全选的读取方式支持并发读取,原理是根据表的主键将所有加载到的数据根据scan.incremental.snapshot.chunk.size(默认值是8096)进行切分,例如100w数据就是切分成 100w ÷ size 个chuck,然后这些chuck根据程序分配的并行度读取器并行读取,这样能做到snapshot阶段的多并行,且可以以chunk为粒度进行checkpoint

在这里插入图片描述

debezium官方文档

Debezium是flink-cdc的底层采集工具,其官方文档也是建议MySqlConnector实例的进程中server id唯一且需设置在范围1——232-1之内。

根据获取到的信息,我手动给他根据给这两个相同实例的任务设置不同的server id,程序1并行度是10,我将server id设置成1-11,程序2并行度是16,我将server id设置成12-28,程序果然能长时间正常运行,没有再出现结束snapshot阶段进入binlogReader阶段时报错server-id冲突。

事情到这里就结束了吗,并没有!!!
如果这个实例只是一两个任务,那手动设置server id还可以,如果这个实例有需求上百上千个任务,或者我想把它集成到数据集成平台中呢,我一个一个任务启动时还需要去代码中配置server-id,那大量的开发时间就会浪费掉!

一了百了

有没有自动化的方法呢?of course 这里我尝试了2个方法:

  • 当前时间timestamp,范围(timestamp ~ timestamp + parallelism)
  • 查询数据库里面的使用到的server-id,根据查询到的server-id进行排序,取每次查询到的max(server-id)取该值~max(server-id) + parallelism

果不其然,第一个方案很快就成功了。

System.currentTimeMillis() / 1000

但是有个弊端,由于毫秒超出server-id最大值范围,需要保证任务不是一次性批量启动的,要保证并行度的秒数内不同时启动才可以,比如第一个任务启动的是20并行度,第二个任务需要20秒后启动;

在尝试开启plan B的时候,遇到了比较多的问题,当我执行这个sql语句去查询数据库server-id时。

show variables like 'server_id'

查询出来的结果一直都是1(mysql binlog中设置的my.ini文件里的server-id值),无论程序中运行的server-id改成什么都记录不了,所以直接pass掉方案二。

如果还有什么其他比较好用的方法欢迎交流,创作不易,欢迎转发点赞支持~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值