当前位置: 澳门新濠3559 > 编程 > 正文

高并发及高性能的架构研究澳门新濠3559,新手求

时间:2019-12-27 17:08来源:编程
我从c3p0连接池中获取了一个连接对象con然后设置con.setAutoCommit(false);即设置为手动提交归还连接时直接归还那下次得到同一个连接时还是不是默认的自动提交?新手求解!!! 何涛 1.

我从c3p0连接池中获取了一个连接对象con然后设置con.setAutoCommit(false);即设置为手动提交归还连接时直接归还那下次得到同一个连接时还是不是默认的自动提交?新手求解!!!

何涛

1.TCP/IP心跳包,XE2 DATASNAP本身已内置,设置几个属性就可以,这个经过了测试。不再需要像DELPHI 2010 DATASNAP那样要自己写代码来处理。

spring.dao.exceptiontranslation.enabled

是否开启PersistenceExceptionTranslationPostProcessor,默认为true

spring.datasource.abandon-when-percentage-full

设定超时被废弃的连接占到多少比例时要被关闭或上报

spring.datasource.allow-pool-suspension

使用Hikari pool时,是否允许连接池暂停,默认为: false

spring.datasource.alternate-username-allowed

是否允许替代的用户名.

spring.datasource.auto-commit

指定updates是否自动提交.

spring.datasource.catalog

指定默认的catalog.

spring.datasource.commit-on-return

设置当连接被归还时,是否要提交所有还未完成的事务

spring.datasource.connection-init-sql

指定连接被创建,再被添加到连接池之前执行的sql.

spring.datasource.connection-init-sqls

使用DBCP connection pool时,指定初始化时要执行的sql

spring.datasource.connection-properties.[key]

在使用DBCP connection pool时指定要配置的属性

spring.datasource.connection-test-query

指定校验连接合法性执行的sql语句

spring.datasource.connection-timeout

指定连接的超时时间,毫秒单位.

spring.datasource.continue-on-error

在初始化数据库时,遇到错误是否继续,默认false

spring.datasource.data

指定Data (DML)脚本

spring.datasource.data-source-class-name

指定数据源的全限定名.

spring.datasource.data-source-jndi

指定jndi的地址

spring.datasource.data-source-properties.[key]

使用Hikari connection pool时,指定要设置的属性

spring.datasource.db-properties

使用Tomcat connection pool,指定要设置的属性

spring.datasource.default-auto-commit

是否自动提交.

spring.datasource.default-catalog

指定连接默认的catalog.

spring.datasource.default-read-only

是否设置默认连接只读.

spring.datasource.default-transaction-isolation

指定连接的事务的默认隔离级别.

spring.datasource.driver-class-name

指定driver的类名,默认从jdbc url中自动探测.

spring.datasource.fair-queue

是否采用FIFO返回连接.

spring.datasource.health-check-properties.[key]

使用Hikari connection pool时,在心跳检查时传递的属性

spring.datasource.idle-timeout

指定连接多久没被使用时,被设置为空闲,默认为10ms

spring.datasource.ignore-exception-on-pre-load

当初始化连接池时,是否忽略异常.

spring.datasource.init-sql

当连接创建时,执行的sql

spring.datasource.initial-size

指定启动连接池时,初始建立的连接数量

spring.datasource.initialization-fail-fast

当创建连接池时,没法创建指定最小连接数量是否抛异常

spring.datasource.initialize

指定初始化数据源,是否用data.sql来初始化,默认: true

spring.datasource.isolate-internal-queries

指定内部查询是否要被隔离,默认为false

spring.datasource.jdbc-interceptors

使用Tomcat connection pool时,指定jdbc拦截器,分号分隔

spring.datasource.jdbc-url

指定JDBC URL.

spring.datasource.jmx-enabled

是否开启JMX,默认为: false

spring.datasource.jndi-name

指定jndi的名称.

spring.datasource.leak-detection-threshold

使用Hikari connection pool时,多少毫秒检测一次连接泄露.

spring.datasource.log-abandoned

使用DBCP connection pool,是否追踪废弃statement或连接,默认为: false

spring.datasource.log-validation-errors

当使用Tomcat connection pool是否打印校验错误.

spring.datasource.login-timeout

指定连接数据库的超时时间.

spring.datasource.max-active

指定连接池中最大的活跃连接数.

spring.datasource.max-age

指定连接池中连接的最大年龄

spring.datasource.max-idle

指定连接池最大的空闲连接数量.

spring.datasource.max-lifetime

指定连接池中连接的最大生存时间,毫秒单位.

spring.datasource.max-open-prepared-statements

指定最大的打开的prepared statements数量.

spring.datasource.max-wait

指定连接池等待连接返回的最大等待时间,毫秒单位.

spring.datasource.maximum-pool-size

指定连接池最大的连接数,包括使用中的和空闲的连接.

spring.datasource.min-evictable-idle-time-millis

指定一个空闲连接最少空闲多久后可被清除.

spring.datasource.min-idle

指定必须保持连接的最小值(For DBCP and Tomcat connection pools)

spring.datasource.minimum-idle

指定连接维护的最小空闲连接数,当使用HikariCP时指定.

spring.datasource.name

指定数据源名.

spring.datasource.num-tests-per-eviction-run

指定运行每个idle object evictor线程时的对象数量

spring.datasource.password

指定数据库密码.

spring.datasource.platform

指定schema要使用的Platform(schema-${platform}.sql),默认为: all

spring.datasource.pool-name

指定连接池名字.

spring.datasource.pool-prepared-statements

指定是否池化statements.

spring.datasource.propagate-interrupt-state

在等待连接时,如果线程被中断,是否传播中断状态.

spring.datasource.read-only

当使用Hikari connection pool时,是否标记数据源只读

spring.datasource.register-mbeans

指定Hikari connection pool是否注册JMX MBeans.

spring.datasource.remove-abandoned

指定当连接超过废弃超时时间时,是否立刻删除该连接.

spring.datasource.remove-abandoned-timeout

指定连接应该被废弃的时间.

spring.datasource.rollback-on-return

在归还连接时,是否回滚等待中的事务.

spring.datasource.schema

指定Schema (DDL)脚本.

spring.datasource.separator

指定初始化脚本的语句分隔符,默认: ;

spring.datasource.sql-script-encoding

指定SQL scripts编码.

spring.datasource.suspect-timeout

指定打印废弃连接前的超时时间.

spring.datasource.test-on-borrow

当从连接池借用连接时,是否测试该连接.

spring.datasource.test-on-connect

创建时,是否测试连接

spring.datasource.test-on-return

在连接归还到连接池时是否测试该连接.

spring.datasource.test-while-idle

当连接空闲时,是否执行连接测试.

spring.datasource.time-between-eviction-runs-millis

指定空闲连接检查、废弃连接清理、空闲连接池大小调整之间的操作时间间隔

spring.datasource.transaction-isolation

指定事务隔离级别,使用Hikari connection pool时指定

spring.datasource.url

指定JDBC URL.

spring.datasource.use-disposable-connection-facade

是否对连接进行包装,防止连接关闭之后被使用.

spring.datasource.use-equals

比较方法名时是否使用String.equals()替换==.

spring.datasource.use-lock

是否对连接操作加锁

spring.datasource.username

指定数据库名.

spring.datasource.validation-interval

指定多少ms执行一次连接校验.

spring.datasource.validation-query

指定获取连接时连接校验的sql查询语句.

spring.datasource.validation-query-timeout

指定连接校验查询的超时时间.

spring.datasource.validation-timeout

设定连接校验的超时时间,当使用Hikari connection pool时指定

spring.datasource.validator-class-name

用来测试查询的validator全限定名.

spring.datasource.xa.data-source-class-name

指定数据源的全限定名.

spring.datasource.xa.properties

指定传递给XA data source的属性

唯品会平台架构师

 

何涛,现任职于唯品会平台架构部,要负责数据访问层,网关,数据库中间件,平台框架等开发设计工作。在数据库性能优化,架构设计等方面有着大量的经验积累。热衷于高可用,高并发及高性能的架构研究。

2.XE2 DATASNAP内置的线程池是使用的INDY10的线程池。INDY10是阻塞+多线程的通讯控件。实际测试当中发现DATASNAP是一个客户连接对应一个线程,

大家可能会有这样疑问:连接池类似于线程池或者对象池,就是一个放连接的池子,使用的时候从里面拿一个,用完了再归还,功能非常简单,有什么可讲的。

一直到客户连接断开线程才归还线程池中,就算一个客户连接以后啥事也不干,也要一直地占用服务端一个线程对象。有多少个连接客户,服务端就要开启多少个

可能还会有这样的疑问:高性能这么高大上,一个小小的连接池,如何跟高大上靠上边的。

线程。如果客户数量比较多的话,这样是很没有效率的。开启的线程较多,CPU的时间都花在线程的上下文切换上面。所以在大量并发连接的时候,还是首选完成端口。

本主题将会全面介绍连接池原理,高性能的设计,优化实践,现有连接池的瓶颈及解决方案。同时也会介绍唯品会自研数据库连接池产品(代号:Caelus)

 

为什么要有连接池

3.DATASNAP的线程池满了以后,新开的客户是连接不上服务器的。这时客户的鼠标一直呈等待状态,不会弹出任何提示信息,如果此时有客户关闭连接,

先看一下连接池所处的位置:

那么处于等待状态的客户就会自动连接上服务器。所以设置了线程池的MaxThreads属性以后也就设定了最多的并发连接数量。

澳门新濠3559 1应用框架的业务实现一般都会访问数据库,缓存或者HTTP服务。为什么要在访问的地方加上一个连接池呢?

 

下面以访问MySQL为例,执行一个SQL命令,如果不使用连接池,需要经过哪些流程。

4.实际测试当中,开四百个左右的客户端,每个客户端随机地每隔一秒钟向服务器发出(查询、新增、修改、提交)请求,长时间运行以后,应用服务器仍然健壮地

澳门新濠3559 2

运行,顶不住的是SQL SERVER 2000数据库服务器,会报等待处理的队列过长的错误,SQL SERVER 2000数据库自动暂停服务,需要手工启动以后才能运行。

1:TCP建立连接的三次握手

这说明,真正大量并发的(查询、新增、修改、提交)操作数据的事件会导致数据库当机。对于企业应用来说真正需要处理的是数据,对于企业应用架构来说,要

2:MySQL认证的三次握手

考虑的不仅仅是中间层应用服务器,还有数据库服务器的承受能力。

3:真正的SQL执行

4:MySQL的关闭

5:TCP的四次握手关闭

可以看到,为了执行一条SQL,却多了非常多我们不关心的网络交互。

优点:实现简单。

缺点:

1:网络IO较多

2:数据库的负载较高

3:响应时间较长及QPS较低

4:应用频繁的创建连接和关闭连接,导致临时对象较多,GC频繁

5:在关闭连接后,会出现大量TIME_WAIT 的TCP状态(在2个MSL之后关闭)

使用连接池流程

澳门新濠3559 3

第一次访问的时候,需要建立连接。 但是之后的访问,均会复用之前创建的连接。

优点:

1:较少了网络开销

2:系统的性能会有一个实质的提升

3:没了麻烦的TIME_WAIT状态

当然,现实往往是残酷的,当我们解决了一个问题的时候,同时伴随着另外一个问题的产生。

使用连接池面临的最大挑战: 连接池的性能

连接数和线程数性能优化

分库DB部署结构:

澳门新濠3559 4

假设有128个分库:32个服务器,每个服务器有4个schema。按照128个分库的设计,便会新建128个独立数据库连接池。

数据库连接池的模型

澳门新濠3559 5

特点:

1:128个连接池完全独立,不同的schema也对应不同的连接池

2:先通过拆库,读写等策略选择对应的连接池,再从连接池获取一个连接进行操作

3:操作完后,再将连接归还到对应的连接池中。

优点:

结构简单,分散竞争

面临的问题:

1:线程数过多

先看一下新建一个连接池,需要新建的线程数的个数。

可以看到随着分库的增加,不管选用哪个连接池,线程的个数均会线性增长。线程数过多将会导致内存占用较大: 默认1个线程会占用1M的空间,如果是512个线程,则会占用1M*512=512M上下文切换开销。

Tips:由于stack和heap申请为虚地址空间,但是一旦使用就不会释放。(线程也不一定会占用1M的空间)

2:连接数过多

数据库的连接资源比较重,并且随着连接的增加,数据库的性能会有明显的下降。DBA一般会限制每个DB建立连接的个数,比如限制为3K 。假设数据库单台限制3K,32台则容量为3K*32=96K。如果应用最大,最小连接数均为10,则每个应用总计需要128*10=1.28K个连接。那么数据库理论上支持的应用个数为96K/1.28K= 80 台

3:不能连接复用

同一个物理机下面不同的schema完全独立,连接不能复用

优化后的数据库连接池模型
澳门新濠3559 6

特点:

1:只有一个连接池,所有节点共享线程 (解决了线程数过多的问题)

2:每个物理机对应一个host, host里面维护多个schema,schema存放连接。

3:同一个host下面的不同schema 可以进行连接复用(解决连接数过多的问题)

获取连接流程:

1:获取连接需要带上 ip,port和schema信息:比如获取的是host31的schema1

2:先到host31的schema1中获取空闲连接,但是schema1无空闲连接,便会从schema2中获取空闲连接。

3:从schema2中获取的连接执行useschema1,该连接便切换到schema1上面。

4:执行对应的SQL操作,执行完成后,归还连接到schema1的池子里面。

优点:

1:连接复用:有效减少连接数。

2:提升性能:避免频繁的新建连接。新建连接的开销比较大,而使用use schema开销非常小

3:有效减少线程数。按现有方案大概只需要4个线程即可。而优化前需要512个线程

缺点:

1:管理较为复杂

2:不符合JDBC接口规范。DataSource只有简单的getConnection()接口,没有针对获取对应schema的连接的接口。需要继承DataSouce,实现特定接口。

事务语句性能优化

优化前执行事务的模型
澳门新濠3559 7

从连接池里面获取到连接,默认是自动提交。为了开启事务,需要执行setautocommit=false 操作,然后再执行具体的SQL,归还连接的时候,还需要将连接设置为自动提交(需要执行set autocommit=true) 。可以看到开启事务,需要额外执行两条事务的语句。

优化后执行事务的模型

澳门新濠3559 8
每个schema里面所有的连接会按照autocommit进行分组。 分为自动提交(autocommit=true) 和非自动提交(autocommit=false)。获取连接时优先获取相同autocommit的分组里的连接,如果没有可用连接则从另外一个分组中获取连接,业务操作执行完后,再归还到对应的分组里面。该种机制避免了开启事务多执行的两条事务语句。

锁性能优化

连接池的通用功能:
澳门新濠3559 9

连接池主要包含五部分:获取连接,归还连接,定时任务,维护组件及资源池

获取连接:

1:获取超时:如果超过规定时间未获取到连接,则会抛出异常

2:有效性检查:当从资源池里面获取到资源,需要检查该资源的有效性,如果失效,再次获取连接。避免执行业务的时候报错。

3:创建连接:可以同步创建,也可以异步创建。

归还连接:

1:归还连接:比如需要检查最大空闲数,确定是物理关闭还是归还到连接池

2:销毁连接: 可同步销毁也可异步销毁

定时任务:

1:空闲检查:主要是检查空闲连接,连接空闲超过一定时间,则会关闭连接。

2:最小连接数控制:一般会设置最小连接数。保证当前系统里面最小的连接数。如果不够,则会新建连接。

组件维护:

1:连接状态控制:空闲,使用,删除等状态控制

2:异常处理:对JDBC访问的异常统一处理,如果异常与连接相关,则会将该连接销毁掉。

3:缓存:避免对SQL重复解析,PrepareStatement机制下,会对SQL解析的对象进行缓存。

4:JDBC封装:对JDBC进行了实现,真正的实现是底层的driver,比如MySQL-connector-java 。

资源池:

1:资源池是存放连接的地方,也是连接池最核心的地方。

2:所有的组件基本上都与资源池进行交互,对连接资源的竞争非常激烈。该处的性能将决定了整个连接池的性能。

澳门新濠3559,3:一般资源池的实现是使用JDK提供的BlockingQueue。那么是否有方案可以进行无锁的设计,来避免竞争。

资源池无锁设计
澳门新濠3559 10

获取连接大概流程:

1:从ThreadLocal里面获取连接,如果没有空闲连接,则从全局连接池(CopyOnWriteArrayList)中获取。

2:如果全局连接池中没有空闲连接,则会异步新建连接。

3:判定超时时间是否大于阈值,如果小于阈值,则进行自旋。否则进行park休眠。

4:连接建立成功后,会对park的线程进行唤醒

主要从四个方面实现了无锁的设计:ThreadLocal,CopyOnWriteArrayList,异步建立连接及自旋。

ThreadLocal

1:每个线程均有一个连接队列。该队列是全局队列的引用。

2:获取连接时先从ThreadLocal里面拿连接,如果连接是空闲状态,则使用。否则移除掉,再拿下一个,直到拿不到连接为止。

3:归还连接时,只需要归还到Threadlocal的队列里面,同时设置连接为空闲状态

4:如果使用BlockQueue,获取连接时调用poll,归还连接时调用offer,存在两次锁的竞争。优化后通过CAS避免了两次锁的开销(获取连接时,使用CAS置连接为非空闲状态;归还时,使用CAS置连接为空闲状态)

CopyOnWriteArrayList

1:该队列使用场景是:大量读,少量写的操作,并且存储的数据比较有限。而连接池的场景非常适合采用CopyOnWriteArrayList。

2:在获取连接或者归还连接时,只会通过CAS更改连接的状态,不会对连接池进行添加或者删除的操作。

3:一般连接池连接的个数比较可控,CopyOnWriteArrayList在写操作时会对所有连接进行拷贝,对内存影响不大。

异步建立连接

获取到连接后,判断一下是否有并发正在等待获取连接,如果有,则异步建立连接。避免下一个连接的等待。如果CopyOnWriteArrayList没有空闲连接,则异步建立连接。

自旋

该自旋比较类似于JDK对synchronized的自旋机制。如果发现超时时间大于设定的阈值(比如10微秒),则会进行线程挂起。如果小于设定的阈值,则重新获取连接,进行自选,避免线程的上下文切换带来的性能开销。。

优化小技巧

方法内联优化

1:每调用一次方法,线程便会新建一个栈帧,新建栈帧开销相对比较大

2:JIT在运行时会进行内联优化,多个方法使用一个栈帧,避免栈帧新建过多

3:JIT方法内联优化默认的字节码个数阈值是35个字节,低于35个字节,才会进行优化。(可通过-XX:MaxInlineSize=35进行设置)
澳门新濠3559 11

通过修改上述代码,编译后字节码修改到34个字节,则可以满足内联的条件。

心跳语句选择
澳门新濠3559 12

PrepareStatement模式选择
澳门新濠3559 13

MySQL driver默认是client模式,如果需要开启server模式,需要设置 useServerPrepStmts=true 。PrepareStatement默认的client模式和Statement对于DB端没有区别。大家普遍理解PrepareStatement和Statement的区别是PrepareStatement可以避免SQL注入。但是避免SQL注入是如何做到的?

使用PrepareStatement设置参数的时候,比如调用setString(int parameterIndex, String x),本地会对设置的参数进行转义来避免SQL注入。

执行SQL的时候,会将SQL的?替换成转义后的字符,发送到数据库执行。
澳门新濠3559 14

PSCache
澳门新濠3559 15

MySQLdriver 默认不开启,可通过设置 cachePrepStmts = true 进行开启

QueryTimeout
澳门新濠3559 16

之前也遇到因为开启了queryTimeout,导致连接泄露的问题。

具体可参考:

MySQL driver的bug发现之旅:

关于连接池的最优配置之前做过整理,可参考:

唯品会自研连接池:Caelus

Caelus是唯品会自研的高性能的分布式的数据库连接池。

  1. 高性能:基于无锁的连接池设计模型来提升连接池性能;

  2. 在分库较多的场景下,减少线程数。 假如有128个分库,现有连接池模型下则需要使用128个独立的连接池,每个连接池都需要线程(1-4个,不同的连接池不同)处理任务。则总共需要维护128到128*4个线程,开销巨大。而Caelus连接池会大大减少线程数。

  3. 连接复用。 对于 一个MySQL 的instance上面有多个schema场景下。现有连接池不同的schema的连接不可复用。而Caelus可以复用不同schema的连接,提升性能。

  4. 过多的事务指令。如果是事务语句,则从连接池拿到连接后,需要先开启事务(setautocommit=false),归还时需要再设置(set autocommit=true)。每使用一次连接,均需要额外执行两条事务指令。Caelus能有效减少事务指令。

  5. 配置规范的统一。结合MySQL的设置,提供规范统一,最优的配置。

本主题讲解了数据库连接池的性能设计优化。 关于缓存(Memcache,Redis)

和HTTP连接池的优化实践,后面有机会再和大家一块沟通学习。

关于Netty的纯异步HTTP连接池设计,可参考:

电商技术专题月  |  中生代技术

 

编辑:编程 本文来源:高并发及高性能的架构研究澳门新濠3559,新手求

关键词: