为什么使用HikariCP连接池?

笔者最近在换工作的时,被面试官问数据库和连接池相关的一些问题。 下面从面试这块开始

简单介绍一下笔者项目中数据库的使用情况。项目中使用 MySQL 做数据存储,Redis 做数据缓存。读写数据流程如下:

  1. 数据:先查询 Redis 中是否存在,存在直接取出数据,不存在从 MySQL 查询并保存包 Redis 中缓存起来。
  2. 数据:先写入 Redis,然后异步提交到 MySQL 写入线程,实现数据落地。

问题 1:如何保证数据读写的“原子性”?如何解决脏数据?

众所周知,当使用数据库跨表操作时,利用数据库引擎提供的事务和回滚机制,可以保证数据库跨表操作的原子性。

一方面在项目中引入数据缓存层也是一种常见的减轻数据库压力的做法。另一方面引入了缓存增加了数据操作的复杂度。

如何解决缓存中和数据库中数据不一致的问题? 笔者以线上项目为例简单的说了说。在线上的代码,主要以缓存层数据为主,数据不统一的情况,会在下一次落地时覆盖数据库的数据,实现同步。

假如是因为版本迭代数据库字段变更导致数据库落地错误时,由于 Redis 缓存的有效期是 7 天,在缓存失效前手动执行脚本将数据重新落地。

由于面试官一再强调是自动修复脏数据。 说实话笔者在保证 Redis 和 MySQL 两者数据操作的原子性这块没有什么涉猎。也没想出什么好的办法。 由于面试官一再询问,笔者就稍微讲了讲一个思路回答:也许是否可以使用数据库的原子性,回滚的时候回退数据?

当然事实证明一时的想法总是有漏洞的。数据回退涉及到数据回退前多次被修改的复杂情况。显得不是很合适。

最后引发尴尬的是面试官的总结:(大意如下) 在修改数据前,尽可能多的判定用户是否满足操作的条件,以便于提早发现问题并退出, 以避免数据操作。同时避免异步操作数据库,同步操作及早出现问题并退出。

wtf… 当时一下子感觉自己有点懵逼的。才发现整个就理解错了。瞬间也是好尴尬。

问题 2:HikariCP 是什么?

HikariCP 是一个高性能的 JDBC 连接池。Hikari 是日语“光”的意思。可能是目前 java 业界最快的数据库连接池(BoneCP 因此停止维护,其作者推荐 HikariCP)。 面试官说项目用的 c3p0 作为数据库连接池,也没接触过 HikariCP。还问了何时连接池会关闭数据库的连接。

说实在的,当时笔者没回答好,一般数据库连接池会自动管理数据库连接建立、复用和关闭。一般情况下不会关闭已经建立的数据库连接。 连接池关闭连接方面,其他连接池竞品不清楚,HikariCP 会在设置的最大生命周期后,最大空闲时间后等多个条件作用下自动关闭释放连接。

下面是总结

数据库连接池技术

数据库连接池负责分配、管理和释放数据库的连接。

  1. 数据库连接复用。重复使用现有的数据库连接,可以避免连接频繁建立、关闭的开销。
  2. 统一的连接管理。释放空闲时间超过最大空闲时间的数据库连接,避免因为没有释放数据库连接而引起的数据库连接泄漏。

一些数据库连接池的对比

首先明确:无论任何形式的数据库连接复用(数据库连接池技术)都避免了频繁建立、关闭数据库连接带来的开销。性能相对于没有连接池有质的提升。 另外一点需要明确:数据库连接池一般不会成为整个程序的性能瓶颈。更多的出现在数据库读写,带宽,cpu 等方面(开始人云亦云模式,o(∩_∩)o 哈哈)。

下面引入正文,先来一个对比。 文章数据库连接池性能比对很早之前看到过,但一直没找到原帖。 皇天不负有心人,今天总算是挖出来了原帖(鄙视一下盗链和转帖不挂源地址的)。

HikariCP

HikariCP可能是目前业内最快的数据库连接池。

说到 HikariCP 就不得不说 BoneCP。笔者之前是 BoneCP 的使用者。突然那么一天(忘记具体是哪天了)想看看 BoneCP 是否有新版本。 然后发现 BoneCP 作者在项目主页的描述说不再更新 BoneCP 并且推荐了 HikariCP。

笔者也有段时间没关注这个类库了,面试的时候因为也好久没看了,所以讲的也不是很清楚。于是就抽空复习总结一下。 笔者之前在博客园发表过一篇关于 HikariCP 的文章从 BoneCP 到 HikariCP, 简单讲了 Spring+Mybatis+HikariCP 的配合使用。 那时候刚接触 HikariCP,被官方的测试数据所吸引,毕竟 BoneCP 停产了,而且在代码基本上不需要改动的情况下就能获得更好的性能,何乐而不为呢? 所以决定试试这个“新家伙”

HikariCP 的官方 Wiki 中提到的为什么 HikariCP 是如何实现这么高效率。详细见: Down the Rabbit Hole 掉进兔子洞? 反正我是不懂这是什么谚语。o(∩_∩)o 哈哈。 大概内容如下:

  1. 优化字节码(JVM 内联),减少生成的机器码
  2. 精简代码, 使用 Javassist 生成委托。
  3. 无锁容器。FastStatementList、ConcurrentBag
  4. 等等针对 BoneCP 的优化。(好针对 BoneCP 啊,o(∩_∩)o 哈哈)

Druid

Druid是阿里巴巴开源的“为监控而生的数据库连接池!”。 性能测试过程略低于 HikariCP,但是提供了强大的监控和扩展功能。支持 psCache。

有兴趣可以去 GitHub 查看。有中文文档。o(∩_∩)o 哈哈。阿里威武

结论

为什么使用 HikariCP? 首先它是一个优秀的数据库连接池,代码少,效率高。 支持多种常见的数据库(包含但不限于:Oracle、MS SQL Server、MySQL、PostgreSQL) 轻松集成 Spring+Hibernate/Mybatis。 而且笔者平时的业务内容不是特别需要监控这么“重度”的功能。有慢查询日志基本上就足够了。

知识共享许可协议

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 TinyZ Zzh (包含链接: https://tinyzzh.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。 如有任何疑问,请 与我联系 (tinyzzh815@gmail.com)

TinyZ Zzh

TinyZ Zzh

专注于高并发服务器、网络游戏相关(Java、PHP、Unity3D、Unreal Engine等)技术,热爱游戏事业, 正在努力实现自我价值当中。

评论

  点击开始评论...