# [Known-Issues]关于TiCDC 同步到 Kafka 报错 Message was too large 的问题

## Key Words

TiCDC, binlog, Kafka, message was too large

## Description

使用 TiCDC 同步到 Kafka 遇到报错 \[CDC:ErrKafkaAsyncSendMessage]， kafka server: Message was too large，详细信息如下

```golang
"message": "\[CDC:ErrKafkaAsyncSendMessage]kafka: Failed to produce message to topic ticdc-shadow-cluster-topic-2: kafka server: Message was too large, server rejected it to avoid allocation error."
```

## 背景信息

在处理问题前，需要先了解 TiCDC 同步到 Kafka 的原理

![know-issue-ticdc-kafak-large-message](/images/TiCDC/know-issue-ticdc-kafak-large-message.png)

系统架构如上图所示：

* **TiKV** ：输出 KV 变更日志（KV Change Logs）。KV 变更日志是TiKV 生成的 row changed events，隐藏了大部分内部实现细节。TiKV 负责拼装 KV 变更日志，并输出到 TiCDC 集群。

* **Capture** ：TiCDC 的运行进程。一个 TiCDC 集群通常由多个 capture 节点组成，每个节点负责拉取一部分 KV 变更日志，排序后输出到下游组件。一个TiCDC 集群里有两种 capture 角色：owner 和 processor。

* **Sink** ：TiCDC 内部负责将已经排序的数据变更同步到下游的组件。TiCDC 支持同步数据变更到多种下游组件。

* **TiCDC Open Protocol** ：是一种行级别的数据变更通知协议，为监控，缓存，全文索引，分析引擎，异构数据库的主从复制等提供数据源。

* **Sarama** ：Kafka 中使用，是一个纯 Go 客户端库，用于处理 Apache Kafka (0.8 及更高版本)，它包括一个用于轻松生成和使用消息的高级 API，以及一个用于在高级 API 不足时控制线路上的字节的低级 API。

## Root Cause

Kafka server: Message was too large 错误原因可以归结为：TiCDC 发送了一条过大的数据到 Kafka Producer。

* CDC's Limit 是 max-message-bytes 参数大小。

* Kafka Producer's limit 是 Kafka Topic 的 max.message.bytes 参数值大小。

* Row A 代表单行数据的大小。

正常场景

```yaml
|<-------------------------Kafka Producer's Limit = 10M ---------------------->|<--overflow-->|
|<------------------------- CDC's Limit = 10M -------------------------------->|<--overflow-->|
|<------------- row A = 5M ---------------------->|<--still space here->|
```

## Workaround

### 通用方案

#### 原因

遇到 kafka server: Message was too large 的报错，场景一和二都可以归结为参数配置导致

#### 解决方案

检查参数配置，根据以下原则：

* 假设单条数据 row 大小为 a，那么 a 一定不大于 max-message-bytes 参数值

* TiCDC 中 max-message-bytes 参数值，不大于 Kafka Topic 的 max.message.bytes 参数值

根据单条 row 数据大小修改 TiCDC 和 Kafka 参数值满足以上条件。

### 其他方案 

> **注意**
>  
> 当检查完通用方案无法解决时，可以参考以下方案。

#### Case 1

##### 原因

Kafka 内部参数配置不统一导致报错

##### 解决方案

TiCDC 配置参数已经小于或者等于 Kafka 侧参数配置。Kafka 配置参数可以参考 [Kafka 官方文档](https://kafka.apache.org/documentation/)

* **max.request.size**  The maximum size of a request in bytes. This setting will limit the number of record batches the producer will send in a single request to avoid sending huge requests. This is also effectively a cap on the maximum record batch size

* **message.max.bytes**  The largest record batch size allowed by Kafka

* **replica.fetch.max.bytes**  The number of bytes of messages to attempt to fetch for each partition. This is not an absolute maximum if the first record batch in the first non-empty partition of the fetch is larger than this value, the record batch will still be returned to ensure that progress can be made. The maximum record batch size accepted by the broker is defined via message.max.bytes (broker config) or max.message.bytes (topic config)

#### Case 2

##### 原因

TiCDC BUG，由于 Mqsink 中没有限制 max-message-bytes 的大小，导致发送到 kafka 的消息超过参数值

##### 影响版本

[v4.0.0,v4.0.8]

Github Issue [https://github.com/pingcap/tiflow/issues/1059](https://github.com/pingcap/tiflow/issues/1059)

##### 解决方案

升级到 v4.0.9 及以上版本修复

#### Case 3

##### 原因

由于批量组合发送消息，到达 Kafka 侧需要添加 overhead ，导致消息大小超过参数配置

##### 影响版本

\[v4.0.0,v4.0.15],\[v5.0.0,v5.0.5],\[v5.1.0,v5.1.2],\[v5.2.0,v5.2.1]

Github Issue：[https://github.com/pingcap/tiflow/issues/2962](https://github.com/pingcap/tiflow/issues/2962)

PR：[https://github.com/pingcap/tiflow/pull/3002](https://github.com/pingcap/tiflow/pull/3002)

##### 解决方案

升级到 v4.0.16，v5.0.6，v5.1.3，v5.2.2 及以上版本修复