为什么 IoTDB 选择 Java?权衡之后的最优解

从 16 年开始参与时序数据库 IoTDB 的研发,时不时的会被问到,你们为什么用 Java 写数据库?Java 能用来写数据库吗?
最开始我会讲,“在 IoTDB 起步的 2011 年,几乎所有知名系统、数据库,都采用 Java 进行开发,像 Hadoop、Hbase、Spark(基于 JVM 的 scala)、Cassandra、Kafka、Flink,为了和大数据生态的紧密结合,IoTDB 自然选择了 Java 进行开发。”
这是一个原因,但我相信大家想了解的绝对不仅仅是这些。那么,学了 Java,有没有机会做数据库?Java 能不能做出好的数据库?选择 Java 开发,对于 IoTDB 意味着什么?
这些问题无法通过理论推导,Java 与数据库,是语言、系统、投入、回报的辩证组合,只能实践出真知。而我们经过了近 10 年的探索,今天来重新回答这个问题,主要有以下 8 个方面的考虑。
1. Java 生态丰富
队列、Map、堆、锁、线程控制等,凡是通用的数据结构和算法,几乎都有成熟的实现,这让我们可以把精力投入到数据库逻辑优化中,而不是重复造轮子。
此外,大量的平台和应用在使用 Java 开发,Java 生态的中间件和软件互相集成的便捷度很高,也促使了 Java 应用开发者对 Java 语言的数据库的可掌握程度就更高。
2. 可读性
这个点没有放在第一位,是因为大家一般不太会关注,但是作为一个长年摸爬滚打的数据库研发者,这个因素也非常重要。
数据库的高复杂度,不仅仅带来巨大的优化空间,也同时带来了极度危险,稍不注意就会写入 bug,这也是为什么有的数据库新版本会比老版本的性能和稳定性差很多。
而面向对象的 Java,在代码可读性和易理解层面,具备天然优势。在和社区贡献者的交流过程中,发现大家对 IoTDB 的设计原理基本能够很快上手。
代码可读性是一个系统的生命力,可读的代码才能让一个系统在演进过程中保持长期的活力。
3. 运维难度
相信 Java 开发者都会对其异常捕获机制和在日志中打印的堆栈印象深刻。这些堆栈信息能够帮我们快速定位问题并进行修复。印象中,如果用户反馈 IoTDB 的 bug,通常能根据堆栈信息,在当天定位问题原因并进行修复,很少超过 1 天的。
之前和一些 C 语言数据库的开发者交流,遇到内存泄露等线上问题时,排查时间在一个月以上都是可能的。
和数据库整体稳定性相比,任何语言特征优势都要靠后,没有什么比线上数据库出问题不能快速修复更让人崩溃了。JProfiler、Arthas 等 JVM 运维神器能够帮助 Java 开发者快速定位到问题原因,及时修复。
4. 跨平台
最近这个词有另一个叫法:国产化适配。Java 的目标就是“一次编译,到处运行”,随着这几年国产硬件的大范围普及,我们几乎没有做过任何特殊的适配工作,只要能装上 Java 就能使用 IoTDB。让我们能够把精力放在数据库内在逻辑的优化和打磨。
5. 便捷的项目管理
参与 IoTDB 项目学习的第一个技能就是 Java 项目管理工具 Maven。不论大小,Java 项目几乎都在使用 Maven 进行管理。包括代码结构组织、依赖管理、编译、打包、版本发布等,一些代码格式化、静态检查等高级操作也能通过自定义的 profile 一气呵成,上手非常快,我写博客的起点就是介绍 Maven 项目的发版流程。
6. 性能
相信这是大多数人会关注的,Java 开发的数据库性能会高吗?
先放个事实,在目前主流的公开时序数据库榜单上,比如 TPCx-IoT、BenchAnt,IoTDB 在读写性能、成本维度都是第一。这些榜单中包括了 Go 语言的 InfluxDB 和 VictoriaMetrics、C 语言的 TimescaleDB、C++ 语言的 Clickhouse 等。
Java 开发的 IoTDB,性能不仅不差,反而是最好的,这是什么原因?
数据库被誉为基础软件皇冠上的明珠,其研发难度之大超乎想象,这里的研发难度来自哪里?不是语言的复杂度,而是数据库内的逻辑复杂度。
随着数据库功能的丰富,数据库迭代演进的困难会随指数级增长,就像一个大型城市治理,有各种部门、流程、人员、资源要协调,也会越来越笨重冗余。这里面可以优化的点就非常多,列式存储、批量化、流水线、索引,很有可能一个细节流程的优化,就带来 10 倍的性能提升。
大家经常提到的 Java 垃圾回收,本身是一个正面特性,就像操作系统的内存碎片整理,全世界的优秀 Java 开发者实现的垃圾回收,整体表现还是不错的。特殊场景中如果需要专门优化,通过在数据库层面设计缓存、甚至使用堆外内存,也能够做到应用层无感。
数据库是个综合的系统,单一的技术优势和技术劣势都不足以定义一个数据库,在我们维护的线上环境从来没有碰到过 Java GC 算法表现不够的场景,如果碰到了严重 GC 停顿,要么是使用问题,要么是遇到了内存泄漏,但是这些问题在测试阶段通常当天就能掉解决了。
7. 轻量化
也遇到有人关心,我们是端侧场景,Java 能做到轻量部署吗?这里分两个场景讨论。
第一种是智能终端,可能只是资源没那么多,单核 CPU、1-2G 内存、几十 G 磁盘空间,但是也是有完整的软件开发环境的。这种都没啥问题,IoTDB 内存可以调节到百兆左右,性能完全能够满足边缘读写负载,目前 IoTDB 在卫星、机载、电力采集终端等的应用都是这种场景。
第二种是嵌入式场景,只支持 C/C++ 环境,内存几十兆,需要实时采集数据,存储上传。这种场景真的需要数据库吗?其实大多情况文件就够用,我们一般使用时序数据文件格式 TsFile 的 C++ 版进行端侧存储,然后再将文件上传。(C++ TsFile 会于近期开源发布)
可能大家会想,端侧部署数据库能不能用来进行工业控制优化,或者控制算法需不需要长期历史数据进行计算?一般不会,控制算法的时间复杂度通常会控制在非常低的程度,保证控制实时性,即使需要一段时间的历史数据,也会采集后就全量缓存在内存里直接用,不会写数据库再读出来进行计算。
当终端向着智能化发展,硬件资源会越来越充足,我们需要更聚焦数据处理机制。
8. Java 人才济济
数据库公司和核心不仅仅是代码,还有一个靠谱的开发和运维团队。
数据库领域在前几年爆火的一段时间吸引了不少人参与,但是总体占比还是太少了。而优秀的 Java 开发者来参与数据库内核开发,这条路已经被我们反复验证是可行的,而且大家转型的效果往往很好,都能够快速维护起一个模块,开始投入代码贡献。
---------------------------
既然如此,大家为什么依然觉得 Java 不能写数据库呢?很大一部分原因在于,老牌关系数据库 Oracle、MySQL、PostgreSQL 都不是 Java。
这其实是一个历史原因。传统关系数据库诞生于 1970 年,而 Java 是 1995 年才诞生的,在 Java 诞生时,这些数据库已经用 C 语言写了几十年了:Oracle(1977)、PostgreSQL(1986)、MySQL(1995)。
在 Oracle 成立之初,也有人对数据库能否成功商业化抱有疑问。而 Oracle 的成功用实践证明了数据库是可以商业化的。
Java 也是一样,很多高性能中间件和数据库都在用 Java 开发,包括 IoTDB、Cassandra、H2 等大量实践证明 Java 的性能是足够开发数据库的。
回顾 IoTDB 发展的十年时间,我们之所以能在近几年用户需求爆发时快速迭代出用户需要的核心功能,并且保持了高稳定性和性能,这里一定有 Java 的一份功劳。
Java 不仅能做数据库,而且很合适。这不是一个理论推导,而是实践结论。
如果你也是一位 Java 开发者,是完全有机会做出一款优秀数据库的,如果对 IoTDB 感兴趣,欢迎点击:https://github.com/apache/iotdb 来 GitHub 逛逛。
评论