Debezium系列- snapshot写入慢采坑记录

问题描述

测试集群使用Debezium snapshot一张 2000多万的表耗时 40多分钟,使用线上集群snapshot 耗时 6小时51分钟,线上集群snapshot慢了10倍

问题分析

测试集群和线上集群不同

  • 测试集群kafka单个broker,线上集群3个broker每个broke挂4个盘
  • 测试集群默认创建topic Replicas=1,线上集群 Replicas=2

排查过程

开始怀疑是线上磁盘可能有坏道导致写入慢,联系运维排查磁盘OK。有点怀疑是副本数的问题,由于对kafka有一定的了解,感觉多一个副本数对写入性能影响不会这么大,不太相信是因为副本数的引起问题。同时找了前辈的性能测试文章的发现确没有这么大影响(https://www.cnblogs.com/arli/p/12574524.html),为了验证猜想还让运维的同学利用kafka压测工具做了副本数对写入影响的测试,结论是一个副本 ack=1和ack=-1的情况情况下并没有10配这么明显的差异,只是由小的波动。这里有个坑因为之前使用过kafka知道producer的ack默认配置是1的,由此推出connector使用的producer写入ack也是1。更坚信不是因为副本数引起的写入慢。于是只能查看Debezium的源代码。由于之前踩过时间问题的坑,阅读起来还是比较顺利的,只找到了Debezium采集后将其转换成了SourceRecord (io.debezium.connector.mysql.RecordMakers#assign),找不到producer写数据到kafka的代码和相关配置的代码。全局搜索也没有。心中有些沮丧。然后google一波connector source的写入流程,然而并没有太多的介绍。耐心的去官网学习(https://docs.confluent.io/current/connect/design.html),同时看了kafka的connect源码,发现org.apache.kafka.connect.runtime.Worker#producerConfigs 如下图,默认ack=all

static Map<String, Object> producerConfigs(ConnectorTaskId id,
                                               String defaultClientId,
                                               WorkerConfig config,
                                               ConnectorConfig connConfig,
                                               Class<? extends Connector>  connectorClass,
                                               ConnectorClientConfigOverridePolicy connectorClientConfigOverridePolicy) {
        Map<String, Object> producerProps = new HashMap<>();
        producerProps.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, Utils.join(config.getList(WorkerConfig.BOOTSTRAP_SERVERS_CONFIG), ","));
        producerProps.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.ByteArraySerializer");
        producerProps.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, "org.apache.kafka.common.serialization.ByteArraySerializer");
        // These settings will execute infinite retries on retriable exceptions. They *may* be overridden via configs passed to the worker,
        // but this may compromise the delivery guarantees of Kafka Connect.
        producerProps.put(ProducerConfig.REQUEST_TIMEOUT_MS_CONFIG, Integer.toString(Integer.MAX_VALUE));
        producerProps.put(ProducerConfig.MAX_BLOCK_MS_CONFIG, Long.toString(Long.MAX_VALUE));
        producerProps.put(ProducerConfig.ACKS_CONFIG, "all");
        producerProps.put(ProducerConfig.MAX_IN_FLIGHT_REQUESTS_PER_CONNECTION, "1");
        producerProps.put(ProducerConfig.DELIVERY_TIMEOUT_MS_CONFIG, Integer.toString(Integer.MAX_VALUE));
        producerProps.put(ProducerConfig.CLIENT_ID_CONFIG, defaultClientId);
        // User-specified overrides
        producerProps.putAll(config.originalsWithPrefix("producer."));


        // Connector-specified overrides
        Map<String, Object> producerOverrides =
            connectorClientConfigOverrides(id, connConfig, connectorClass, ConnectorConfig.CONNECTOR_CLIENT_PRODUCER_OVERRIDES_PREFIX,
                                           ConnectorType.SOURCE, ConnectorClientConfigRequest.ClientType.PRODUCER,
                                           connectorClientConfigOverridePolicy);
        producerProps.putAll(producerOverrides);


        return producerProps;
    }

找到问题了解决就简单了,面临的就是怎么覆盖这个参数的问题了。

解决方案

覆盖connect默认的producer的ack配置,需要将connector.client.config.override.policy=All 即可在注册connector是通过 producer.override.*和consumer.override.*来分别指定覆盖 producer和consumer的配置。参数优调对比(partition=1,replice=2)
在这里插入图片描述
从上面数据明显看出使用avro序列化,snappy压缩 ,ack=1,有明显的吞吐量优势,如果可用性要求很高 acks=all。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值