主流数据库连接池常用的主流开源数据库连接池有C3P0、DBCP、TomcatJdbcPool、BoneCP、Druid等C3p0:开源JDBC连接池实现数据源和JNDI绑定,支持JDBC3规范和JDBC2标准扩展。目前使用的开源项目有Hibernate、Spring等。单线程,性能较差,适合小型系统,代码600KB左右。DBCP(DatabaseConnectionPool):Apache开发的Java数据库连接池项目,Jakartacommons-pool对象池机制,Tomcat使用的连接池组件就是DBCP。单独使用dbcp需要3个包:common-dbcp.jar、common-pool.jar和common-collections.jar。数据库连接是预先放在内存中的。当应用程序需要建立数据库连接时,可以直接在连接池中申请一个,使用后放回原处。单线程,低并发,性能差,适合小型系统。TomcatJdbcPool:Tomcat在7.0之前使用common-dbcp作为连接池组件,但是dbcp是单线程的。为了保证线程安全,整个连接池都会被锁住。性能很差。dbcp有60多个类,比较复杂。Tomcat从7.0开始引入了一个新的连接池模块,叫做Tomcatjdbcpool。它基于TomcatJULI,使用Tomcat日志框架,完全兼容dbcp,通过异步方式获取连接,支持高并发应用环境,只有8个超级简单的核心文件。JMX支持XA连接。BoneCP:官方说法,BoneCP是一个高效、免费、开源的Java数据库连接池实现库。设计的初衷是提高数据库连接池的性能。根据一些测试数据,BoneCP的速度是最快的,比当时第二快的连接池快了大约25倍。完美集成到一些持久化产品如Hibernate和DataNucleus中。BoneCP特点:高度可扩展且速度快;连接状态切换的回调机制;允许直接访问连接;自动复位能力;JMX支持;懒加载能力;支持XML和属性文件配置方式;更好的Java代码组织,单元测试分支代码覆盖率100%;代码大约40KB。Druid:Druid是Java语言中最好的数据库连接池。Druid可以提供强大的监控和扩展功能。当代码部署、机器故障等产品系统遭遇宕机时,Druid仍能保持100%正常运行。主要特点:专为分析和监控而设计;快速交互查询;高可用性;可扩展的;Druid是一个开源项目,源代码托管在github上。主流连接池的功能对比如下:看一组HikariCP与HikariCP的性能分析:HikariCP通过优化(concurrentBag,fastStatementList)集合提高并发读写效率。HikariCP使用线程本地缓存连接和大量的CAS机制,最大程度的避免了锁。单机可能会导致cpu占用增加。从字节码维度优化代码。(运行服务器Hotspot编译器的JVM默认inlinethreshold是35个字节码)尽可能让方法小到35个字节码,以提高jvm的处理效率。HikariCP做的优化补充如下:mysqlconnector源码使用了ping命令,是比HikariCP更快的数据库连接池。一个同事告诉我,他也用过和研究过一个比hikari更快的连接池https://github.com/mauricio/postgresql-async这是scala生态里的东西。mysql协议是用netty实现的,没有使用官方的mysqlconnector。它是纯粹异步的。它的连接池写的比较随便,但是性能还是很不错的。展望未来,未来是HikariCP还是Druid为主?很多人都在问,站在巨人肩膀上的二代连接池HikariCP和druid哪个好?其实我觉得这是一个不需要讨论的问题。我们先来看看未来的趋势:单机操作系统将被抛弃,取而代之的是具有容器调度和编排功能的云操作系统。裸机或虚拟机的运行时也将被容器取代。服务网格将用于通信。也就是说,中间件的最终趋势一定是弱化到无感知,也就是极简的最终方向。那些maven依赖问题,把二方库写在pom里,把监控代码硬编码到应用里,会逐渐弱化到不存在,而那些java代理(如pinpoint,skywalking等)或者servicemesh将被替换。这种边车模式可以通过中间件(包括连接池)进行监控。有赞的朋友告诉我,在有赞的核心应用中将durid替换为HikariCP后,RT经历了断崖式下降(1.5ms~1.2ms),并持续稳定,几乎没有毛刺。经过性能测试和压力测试,一个核心系统的性能比druid提升了一倍左右。阿飞做了如下统计工作,全部是根据最新的tag统计,只统计了java文件和xml文件,druid(alibaba-druid)的总行数:430289,HikariCP(brettwooldridge)的总行数-HikariCP):18,372。只统计java代码,druid(alibaba-druid)总行数:428749,HikariCP(brettwooldridge-HikariCP)总行数:17556。然后过滤测试目录,(alibaba-druid)总行数oflines:215232,(brettwoldridge-HikariCP)totalnumberoflines:7960光是一个DruidDataSource就有3000行,性能更不用说了,druid是基于jdbc的,自身编码增强。如果是这样,druid恰恰是生活在第一代和第二代连接池的面向过程的时代。Druid可能忘记了松散耦合的概念。在一个项目中结合监控和数据库连接池本身就是紧耦合。既然微服务提倡业务隔离,这个不应该隔离吗?让组件工具一次只做一件事不是很好吗?毕竟未来servicemesh还有其他天然的监控方式可以监控,而不是硬编码在一个小的连接池里。综上所述,无论是现在还是未来的趋势,大概率都比不上拥抱springboot2.0,精简到极致的HikariCP。未来的中间件一定要像springecosystem和servichmesh一样。路很简单,越来越细。升级中间件不再需要用户强行升级maven依赖来解决依赖冲突,而是通过mesh升级到极致让业务方毫无察觉。因此,热部署、Pandora启动、容器隔离等解决依赖冲突的折衷方法将大概率被替代。从Sharding-jdbc架构的演进看未来的DatabaseMesh,这是一个源于ServiceMesh浪潮的新兴词汇。顾名思义,DatabaseMesh通过一个网格层来统一管理分散在系统各个角落的数据库。通过网格层收集的应用程序和数据库之间的交互网络像蜘蛛网一样复杂而有序。它的主要目标不是网格化存储在数据库中的数据,而是网格化应用程序和数据库之间的交互。DatabaseMesh的重点是如何将分布式数据访问应用程序和数据库有机地连接起来。它更注重交互,就是有效梳理杂乱的应用程序和数据库之间的交互。使用DatabaseMesh,访问数据库的应用程序和数据库最终将形成一个巨大的网格系统。应用程序和数据库只需要在网格系统中注册。它们都是由网格化层管理的对象。Sharding-JDBC一直以JDBC层分片为核心概念。其架构图如下:Sharding-JDBC将实现Driver、Server和Sidecar三个不同版本,共同构成Sharding-JDBC生态,针对不同的需求和环境提供更有针对性和差异化的服务。由于Sharding-JDBC-Server的出现,弥补了原有DBA无法通过Sharding-JDBC-Driver操作数据的缺陷。由于Sharding-JDBC-Driver不需要通过代理层重新转发,在线性能更好。Sharding-JDBC可以通过以下混合部署方案使用:线上应用使用Sharding-JDBC-Driver直接连接数据库以获得最佳性能,使用MySQL命令行或UI客户端连接Sharding-JDBC-Server以方便查询数据并执行各种DDL语句。它们使用同一个注册中心集群,注册中心可以通过管理端配置注册中心的数据,自动推送配置变更给Driver和Server应用。如果因为数据库拆分太多导致连接数暴涨,可以考虑直接在线使用Sharding-JDBC-Server,有效控制连接数。在不久的将来,Sharding-JDBC-Sidecar也会问世,其部署架构如下:基于Sharding-JDBC的DatabaseMesh和ServiceMesh互不干扰,相辅相成。服务之间的交互由ServiceMeshSidecar接管,基于SQL的数据库访问由Sharding-JDBC-Sidecar接管。对于业务应用,无论是RPC还是访问数据库,都无需关注其真实的物理部署结构,做到真正的零入侵。由于Sharding-JDBC-Sidecar随着宿主机的生命周期而产生和消亡,因此它不是静态IP,而是完全动态弹性的存在,整个系统中没有中心节点。对于数据运维等操作,仍然可以启动一个Sharding-JDBC-Server进程作为静态IP入口,通过各种命令行或UI客户端进行操作。
