3.1 Hikari背景、特色及前景
在HikariCP GitHub官网上写着图灵奖获奖者Dijkstra的一句话:“Simplicity is prerequisite for reliability”,翻译成中文大意是“简单是可靠性的先决条件”。HikariCP在致敬前辈的同时,也真正做到了简单、极致。其官网首页的定义是:Fast, simple, reliable. HikariCP is a “zero-overhead” production ready JDBC connection pool. At roughly 130Kb, the library is very light.翻译成中文的意思就是:快速,简单,可靠。HikariCP是一个“零开销”的JDBC连接池产品。它的库非常轻量级,大约130Kb。
Hikari日语发音是Hi-ka-li(里),其作者在GitHub首页及作者Wooldridge的采访中都详细提到了其正确的发音:
I've lived and worked in Tokyo since 2008, though I think my Japanese is far behind where it should be given my time here. I chalk that up to preferring time at the keyboard to language study.
【译】自2008年以来,我一直在东京生活和工作,但我认为我的日语水平远远落后于我曾在这里待的时间。我认为比起语言学习,我更喜欢在键盘前学习。
As you mentioned, Hikari (pronounced Hi-ka-lee) translates to “Light” (as in sunlight). In English, it is a double entendre in the context of HikariCP; though in Japanese it would not be.“Light” in the sense of “the speed of…”, and “light” in the sense of being light in terms of code weight.
【译】正如你(采访记者)提到的,Hikari(发音为Hi-ka-lee)翻译成“光”(在阳光下)。在英语中,HikariCP在语境中是双关语;但是在日语中并不是这样的。“光”的意思是“…的速度”, “光”的意思是代码量很小。
Hikari虽然是日语,但是其作者却是一个从2008年一直生活在日本东京的地道的美国人。Hikari的意思是光,HikariCP的意思是Hikari Connection Pool,就是Hikari连接池。从以上作者的描述中可以看到,作者之所以取这个名字是按照英文的语境给这款连接池赋予了两个意义:速度快、代码量小。从这个名字就可以看出,HikariCP的特色和优势就是快。
小窍门
IDEA开发工具的Translation插件,可以听到单词的语音和某些技术词汇的原产地,比如redis是意大利语,lombok是印尼语,Hikari是日语。
HikariCP的出现的背景来源于BoneCP。在BoneCP官网上的Readme中只有简单的一段“遗言”,说了一段历史,如图3-1所示。翻译成中文的意思就是:“BoneCP是一种Java JDBC连接池实现,通过最小化锁争来为应用程序提供更高的吞吐量,从而实现高性能。它击败了较旧的连接池,如C3P0和DBCP,但现在应该被视为弃用,以支持HikariCP。”
图3-1 BoneCP官网上的Readme
HikariCP到底是何方神圣,竟能让曾经叱咤风云的数据库连接池开源产品放弃更新后“白帝托孤”?我们看一下HikariCP作者Brett Wooldridge在2017年2月21日的专栏中公布的其访谈文章。这篇文章中提供了一些HikariCP不为人知的背景故事,其中就包括HikariCP的创建初衷。
小知识
国外有一个专栏叫做jOOQ Tuesdays series,该专栏在每个月的第3个星期二会发布一篇在IT行业中令人兴奋的人的访谈文章。采访人员包括那些使用SQL、Java、开源软件和各种其他相关主题的人员。
多年以前,Brett Wooldridge为其工作的公司创建了一个产品原型,当时,Brett Wooldridge需要一个数据库连接池。和大多数开发者一样,作者只想使用数据库连接池,然后继续他的工作,因此他在网上找到了最受欢迎的库。不幸的是,在对原型进行负载测试时,他所在的技术团队开始遇到死锁,并且异常表明线程之间的连接状态丢失了。
因为数据库连接池是开源的,所以他认为只需要下载源代码,找到并且修复问题,然后贡献给社区即可(其实这也是大多数人使用开源项目的方式,先能够用起来,遇到坑了,研究,然后修复,贡献给社区)。不过当Brett Wooldridge打开这款数据库连接池源码的时候,他却发现这个小小的数据库连接池居然有上千行代码,远远超过他的预料。另外,代码中充斥了大量的锁和嵌套,一些资源在一个方法中被请求却在另一个遥远的地方被释放。这样混乱的代码,即使发现并修复了遇到的问题,也根本无法推断潜在的问题的潜伏的地方。
Brett Wooldridge又换了一个开源的连接池并且检查了它的代码。锁语义更清晰,但代码量仍然是他预料的2倍,特别不能容忍的是这款开源代码将核心连接池逻辑委托给一个单独的库。
此外,Brett Wooldridge研究的所有池都以多种方式违反了JDBC规约。在尽可能的情况下,连接池应该返回一个连接connection,该连接connection和连接池已经释放的连接connection应该是无法区分的。但是,当连接关闭或者返回,或者清除警告,或者回滚未提交的事务时,这些连接池并不会自动关闭语句Statements。并且它们不会重置用户更改的属性,如自动提交或事务隔离级别,以及更多的一些参数,从而导致下一个消费者获得将“脏”连接。
于是Brett Wooldridge就想:“真的吗?难道这就是Java 20年后生态系统中连接池的状态?”出于挫败感和必要性,Brett Wooldridge创建了HikariCP。
很多连接池都是可以直接使用的,那么是什么理由使HikariCP脱颖而出呢?正确性和可靠性是很难出亮点的方向,所以Brett Wooldridge就专注于性能,并从一个简单的推文开始逐渐分享他的数据库连接池之旅。这样的影响就像滚雪球一样越来越大,一些用户在推特上发布了关于HikariCP性能提升和可靠性提升的信息,并且在2015年的某个时候,Wix工程团队写了一篇关于切换到连接池HikariCP的博客。
从本质上来说,性能极致的口碑使得HikariCP越来越受欢迎,这也是大多数用户推崇HikariCP的出发点。但是Brett Wooldridge还是非常希望随着时间的推移,更多的用户会同样重视正确性和可靠性,否则性能就毫无意义,而HikariCP确实也做了很多与正确性和可靠性相关的工作。
在追求极致方面,Brett Wooldridge尝试了一系列的优化,这些优化不是低级的代码优化,而是包含算法优化以外一些更为极致的事情。Brett Wooldridge以基准测试benchmarks作为参照工具,研究了JMH微基准框架,他发现JVM执行了一系列惊人的优化,如果一个人不小心,那么在代码中看起来很聪明的优化只会混淆JIT基于模式的优化器,结果反而会慢而不是更快。为了有效地优化JVM,除了JIT之外,还必须了解Java内存模型(JMM),以及它如何映射到x86等CPU架构。他阅读了JIT源代码,并且熟悉诸如死代码消除、循环不变提升、常量传播、虚拟调用内联等概念。共享状态的竞争是大多数瓶颈的根源(参见前面提到的JMM),所以最近最大的性能提升(例如,在v2.6.0中)来自于简单地避免它的技巧,这些信息在本书后续章节都会介绍,希望对读者进行中间件的调优有所帮助。
开发一款开源产品,Brett Wooldridge也会得到了很多用户关于产品这样或那样的功能性需求,虽然每个要求都可能很简单,但如果全部采纳会显著增加复杂性和代码大小,而他的初衷还是希望数据库连接池HikariCP足够简单。这点是大家需要注意的,就是Brett Wooldridge很可能会拒绝用户的一些扩展性需求,因为他追求的是一条大道至简的路。比如连接读写分离这样的逻辑路由需求就不在HikariCP的未来规划路线图中,Brett Wooldridge倾向于认为这些更多的是Spring层应该去做的行为,而并不属于数据库连接池技术的范畴。
当然,这并不是说Brett Wooldridge不会添加新功能,不去更新HikariCP,相反,HikariCP至少在近几年内的更新升级是比较频繁的。比如,HikariCP的配置,作者认为配置的选项和维度越多,用户就越难以优化配置池。但是,最终有足够的用户需要动态调整大小,并且缺少这种用户是采用的障碍,因此增加了这方面的支持。原则上,他不希望因缺乏动态的大小支持而剥夺用户对HikariCP的可靠性和正确性的认可。
Brett Wooldridge可能拒绝绝大多数功能要求,我们翻看GitHub上的文章就能看到作者拒绝了很多功能请求。作为HikariCP的监护人,保持简单和真实的核心理念符合社区的最佳利益。在代码和配置方面,Brett Wooldridge总是尽量减少“表面积”(通常,对于HikariCP的用户而言,“表面积”表示配置参数的数量)。API的表面积越大,理解起来就越困难。
HikariCP的应用前景和未来发展也是非常可观的。SpringBoot 2.x已经官方宣布使用HikariCP作为SpringBoot默认的数据库连接池,随着SpringBoot和微服务的蓬勃发展,HikariCP在全球范围内的使用一定也会更加普及。