我们团队花了两个月时间调研和试用Apache Hudi,最后还是放弃了。本文记录了我从入门到放弃Hudi的完整经历,包括为什么选择Hudi、学习过程、遇到的各种坑、为什么最终放弃、以及最后的经验总结。如果你在考虑使用Hudi或者其他数据湖技术,希望这篇文章能帮你少走弯路。
一、为什么选择Hudi
先说说我们为什么要调研Hudi。
我们的业务需要一个支持实时更新的数据湖。传统的数据湖(比如Hive on HDFS)只支持追加写入,不支持更新和删除。如果要更新数据,只能全量覆盖,效率很低。
业务上有很多场景需要实时更新,比如用户画像的更新、订单状态的变更、数据的修正。这些场景用传统的数据湖很难满足需求。
这时候我们了解到了Apache Hudi。Hudi是一个流式数据湖框架,支持在数据湖上进行插入、更新、删除操作,而且支持近实时的数据查询。听起来正好符合我们的需求。
当时Hudi比较火,社区很活跃,版本更新也快。而且Uber、腾讯等大厂都在生产环境用了Hudi,看起来比较成熟。所以我们决定花时间调研和试用一下。
二、入门阶段
刚开始学习Hudi的时候,觉得这个技术很强大。
Hudi的核心概念是把数据组织成文件组,每个文件组有一个基础文件和多个增量日志文件。更新数据的时候,不是修改原文件,而是写增量日志,查询的时候合并基础文件和增量日志。这样就实现了数据的更新,而且写入效率很高。
Hudi支持两种表类型:
- Copy on Write(COW):写的时候复制数据,读的时候直接读,写慢读快
- Merge on Read(MOR):写的时候写增量日志,读的时候合并,写快读慢
Hudi还支持三种视图:
- 读优化视图:只读最新的基础文件,查询快但是可能不是最新数据
- 增量视图:只读取某个时间点之后的增量数据
- 实时视图:合并基础文件和增量日志,读取最新数据
这些概念看起来很清晰,设计也很巧妙。我花了一周时间看官方文档和源码,觉得自己理解得差不多了,就开始在测试环境搭建和试用。
三、遇到的第一个坑:环境搭建
第一个坑是环境搭建。
Hudi的依赖很多,而且和Spark、Hive、HDFS的版本兼容性很复杂。我们用的是Spark 3.0,Hudi当时最新版本对Spark 3.0的支持还不完善,有些功能有bug。
我们试了好几个版本的Hudi,每个版本都有不同的问题。有的版本写入正常但是查询报错,有的版本查询正常但是写入性能很差。最后好不容易找到一个相对稳定的版本组合,环境才搭起来。
光是环境搭建就花了一周时间,这让我有点沮丧。一个成熟的开源项目,环境搭建不应该这么麻烦。
四、遇到的第二个坑:写入性能
环境搭好之后,开始测试写入性能。
我们用的是MOR表,因为MOR写入快。测试数据是一亿条用户行为数据,大概100GB。
最开始写入的时候性能还不错,每秒能写几万条。但是写了几天之后,性能开始下降。原因是Hudi的compaction(合并)任务占用了大量资源。
MOR表需要定期把增量日志合并到基础文件里,这个过程叫compaction。compaction很耗资源,而且会影响写入和查询的性能。如果compaction不及时,增量日志会越来越多,查询的时候要合并很多文件,查询性能会越来越差。
我们调整了compaction的策略,设置了异步compaction,限制了compaction的资源。但是效果还是不理想,要么compaction跟不上,要么影响正常的写入和查询。
而且compaction的时候,如果任务失败了,可能会导致数据文件损坏,需要手动修复。这个过程很麻烦,也很危险。
五、遇到的第三个坑:查询性能
写入的问题还没完全解决,查询的问题又来了。
Hudi的实时视图查询需要合并基础文件和增量日志,这个过程比查询普通的Hive表慢很多。我们测试了几个常见的查询,发现比Hive表慢了2到5倍。
特别是数据量比较大的表,查询性能更差。因为Hudi的小文件很多,查询的时候要读很多小文件,IO开销很大。
Hudi有一个文件清理机制,会定期合并小文件。但是合并小文件也需要资源,而且合并的时候会影响性能。我们调整了小文件合并的参数,但是效果有限,小文件问题一直存在。
而且Hudi和Spark的集成还有一些bug,某些查询会报错或者结果不正确。我们给社区提了几个issue,但是修复速度比较慢。
六、遇到的第四个坑:数据一致性
数据一致性是我们最担心的问题。
Hudi支持事务,写入的时候要么成功要么失败,不会出现部分写入的情况。但是在实际使用中,我们遇到了几次数据不一致的问题。
有一次写入任务失败了,但是部分数据已经写进去了。重试的时候,因为主键冲突,导致数据重复。虽然Hudi有去重机制,但是去重是在compaction的时候做的,在compaction之前查询会读到重复数据。
还有一次,因为compaction失败,导致某个分区的数据丢失了一部分。最后是从上游重新同步数据才恢复的,花了好几天时间。
这些数据一致性的问题,在生产环境中是不可接受的。我们的业务对数据准确性要求很高,不能容忍数据丢失或者重复。
七、遇到的第五个坑:运维复杂度
Hudi的运维复杂度比我们想象的高很多。
普通的Hive表,运维很简单,就是定期清理过期分区,检查文件大小。但是Hudi表的运维复杂多了:
- 需要监控compaction任务,确保及时完成
- 需要监控小文件数量,及时合并
- 需要监控写入延迟,确保数据及时可见
- 需要定期清理旧的增量文件和基础文件
- 需要处理各种异常情况,比如compaction失败、文件损坏等
而且Hudi的监控工具不完善,很多指标需要自己开发。我们花了不少时间做监控和告警,但是还是经常出问题。
对于我们这个只有几个人的小团队来说,维护一套Hudi集群的成本太高了。
八、为什么放弃
综合以上这些问题,我们最后决定放弃Hudi。
放弃的主要原因有几个:
- 稳定性不够:我们试用的版本还有不少bug,数据一致性问题让我们很担心。生产环境不能用一个不稳定的系统。
- 性能不达预期:写入和查询性能都没有达到我们的预期,特别是查询性能,比传统的Hive表慢很多。
- 运维成本高:Hudi的运维复杂度太高,我们团队没有足够的人力来维护。
- 社区支持有限:遇到问题的时候,社区的响应速度比较慢,很多问题需要自己解决。
- 替代方案更合适:我们后来找到了更适合我们业务的方案,就是用Kafka+ClickHouse来做实时数据更新,性能更好,运维也更简单。
当然,Hudi不是不好,只是不适合我们的场景。对于某些场景,比如需要增量数据处理、对查询延迟要求不高的场景,Hudi还是一个不错的选择。
九、经验总结
虽然放弃了Hudi,但是这两个月的调研和试用还是有收获的。这里总结一些经验。
1. 新技术调研要充分
在引入新技术之前,一定要做充分的调研。不要只看官方文档和宣传,要在测试环境充分测试,特别是性能测试和稳定性测试。最好能模拟生产环境的数据量和查询场景,看看能不能满足需求。
我们最开始就是太乐观了,觉得官方说的功能都能用,结果实际用的时候才发现很多问题。
2. 关注运维成本
选型的时候,不要只看功能和性能,还要关注运维成本。一个功能强大但是运维复杂的系统,对于小团队来说可能还不如一个简单但是稳定的系统。
Hudi的功能确实强大,但是运维成本太高了,我们团队承受不起。
3. 不要盲目追新
Hudi当时是一个比较新的技术,社区很火,很多人都在讨论。但是新技术往往意味着不成熟,bug多,文档不完善,社区支持有限。
如果是核心业务系统,建议用成熟稳定的技术,不要盲目追新。新技术可以在非核心业务或者测试环境试用,等成熟了再考虑用到核心业务。
4. 要有备选方案
调研新技术的时候,要有备选方案。如果新技术不行,还有其他方案可以用。不要把所有希望都寄托在一个技术上。
我们当时就是同时调研了Hudi和其他几个方案,最后Hudi不行,就用了备选方案,没有耽误项目进度。
5. 及时止损
如果发现技术选型有问题,要及时止损,不要因为已经投入了很多时间和精力就硬撑。及时放弃不合适的技术,换一个更合适的,反而是更高效的做法。
我们就是在试用了两个月、发现问题无法解决之后,果断放弃了Hudi,换了其他方案。虽然浪费了两个月时间,但是避免了在生产环境出更大的问题。
十、最后的话
从入门到放弃Hudi,这两个月的经历让我学到了很多。
Hudi是一个很有前景的技术,设计理念很先进,功能也很强大。但是它还不够成熟,运维成本也比较高,不是所有团队都适合用。
技术选型没有最好的,只有最合适的。在做选型的时候,要根据自己的业务需求、团队能力、运维成本来综合考虑,不要盲目跟风。
虽然放弃了Hudi,但是我还是会关注它的发展。希望Hudi越来越成熟,越来越好用,未来有机会的话,我还是愿意再试试的。
最后用一句话结束本文:"入门需要勇气,放弃需要智慧。"愿每一个技术人都能在技术选型中做出最合适的选择,不盲目追新,也不固步自封。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录