You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.
已crjry表为例, 主键模型并且分桶为1。现象为: 当表为空的时候一开始写入很快, 随着数据量增加, StreamLoad变得越来越慢, 到最后超时。
## 问题一、主键模型写放大
在Doris中, 主键模型( Unique Key Model) 的实现方式是 **Merge-on-Write (MoW)** 。理解它的工作原理,就能明白为什么您的问题会如此严重。
**Merge-on-Write 工作流程(对于更新或插入操作)** :
1. ** 读取 (Read)**: 当新数据写入时, Doris需要先根据主键找到对应的旧数据行所在的底层文件。
2. ** 合并 (Merge)**: 在内存中,将旧数据行标记为删除,并与新数据行合并。
3. ** 写入 (Write)**: 将合并后的新数据( 包含被删除的旧行和新行) 写入一个新的文件版本( Rowset) 。
这个过程也叫 ** “读后写”** 或 ** “写放大 (Write Amplification)”**。一次逻辑上的写入,在物理层面变成了一次“读取+写入”的操作, 其资源开销远大于直接追加数据的模型( Append Model) 。
## 问题二、数据倾斜
1. ** 底层机制 (Ingredient 1)**: 您使用了**主键模型 (Merge-on-Write)**,这决定了每次写入的成本都很高。
2. ** 写入模式 (Ingredient 2)**: 您的Java应用在进行**高频次的Stream Load**,这意味着在短时间内有大量的“读后写”请求被触发。
3. ** 致命缺陷 (The Catalyst)**: 您的表存在严重的**数据倾斜**,导致所有高频写入请求都砸向了**同一个Tablet** (`tablet_id=1173992`)。
## 故障拆解
1. ** 热点Tablet过载**: 所有高频的、高成本的“读后写”操作全部集中在单一的Tablet上。这个Tablet所在的BE节点的CPU和磁盘I/O被瞬间打满。
2. **Compaction不堪重负** : 每次写入都会为这个Tablet生成一个新的小文件版本( Rowset) 。后台的Compaction任务拼命想把这些小文件合并起来, 但它的速度远远跟不上写入生成的速度。Compaction和写入操作激烈地争抢系统资源, 进一步加剧了BE节点的负载。
3. ** 写入超时 (Doris端)**: 在极高的负载下,某一个写入事务的最后一步——`Publish Version`( 让版本生效) , 无法在规定时间内完成。于是, Doris BE日志中出现了第一个关键错误: `PUBLISH_TIMEOUT`。
4. ** 版本链断裂**: 这个超时的事务虽然在FE( 元数据) 层面可能被认为是成功的, 但在BE( 数据) 层面, 它的版本没有被成功应用。这就造成了Tablet版本链上的一个“空洞”。例如, 成功了版本`325762`,但版本`325763`超时失败了。
5. ** 连锁失败 (Doris端)**: 后续所有发往这个Tablet的写入请求, 比如想写入版本`325764`,都会发现`325763`版本缺失, 于是Doris拒绝写入, 并抛出第二个关键错误: `version not continuous`。
6. ** 请求超时 (客户端)**: 与此同时, 您的Java应用程序还在苦苦等待Doris返回Stream Load的成功响应。但由于Doris内部已经陷入“超时->版本不连续”的恶性循环, 根本无法处理完这个请求。最终, Java客户端的HTTP `ReadTimeout` 被触发,应用日志中抛出了我们看到的异常:`java.net.SocketTimeoutException: Read timed out`。
** 结论:主键模型对数据倾斜和高频更新场景极其敏感**