JDBC 读写分离功能是配合数据库读写分离集群使用的,使用读写分离功能需要开启数据库读写分离集群。JDBC读写分离主旨是通过JDBC驱动实现读写分离,并对应用透明。JDBC内部直接识别语句类型和事务读写状态,把读事务中的读语句分发给备机节点执行,以减轻主机的读语句负载,提高整体DB集群的处理能力。
JDBC 默认使用单机方式,如需开启读写分离功能,需指定连接参数 USEDISPATCH 为 true ,同时配置备机地址与备机端口。配置读写分离的所有参数可在 JDBC连接属性 看到。
1.配置读写分离的基本参数
一般情况下,只需以下5个参数来控制:
#打开读写分离功能,
USEDISPATCH=true
#备机地址
SLAVE_ADD=192.168.8.223,192.168.8.130
#备机端口
SLAVE_PORT=54321,54321
#主机读负载率,备机之间轮询平分
HOSTLOADRATE=33
#底层socket receive的超时时间
socketTimeout=10
2.读写分离的连接池
读写分离的连接池默认关闭,可以通过指定连接参数USECONNECT_POOL为true来开启连接池,同时通过指定连接参数CONNECT_POOLSIZE来指定连接池的大小。
#是否使用连接池缓存连接
USECONNECT_POOL=true
CONNECT_POOLSIZE=10
连接池使用场景,包括:
- 一些应用没有提供连接池中间件,却频繁创建连接造成性能问题;
- 中间件连接池有问题,不好排除时,可以使用JDBC自己的连接池来验证问题。
JDBC自己的连接池的功能局限:
- 只提供初始大小控制,不提供最大连接数控制
- 没有空闲连接回收机制
注:所以基本上只提供连接缓存功能,只适用在临时测试和中间件问题验证上
如果应用已经有了连接池,就不开启JDBC连接池,因为连接池需要锁来管理全局队列,高并发建连接会有性能损耗。如果应用没有连接池,可以开启JDBC连接池,因为频繁建连接是很耗时的行为,开启连接池可以降低应用频繁建连接的损耗。
3.读写分离语句分发策略
读语句分发,分两种情况:
(1)单语句事务,这种情况下每条语句都是一个独立的事务,所以读语句分发备机没有问题。
(2)多语句事务,这种情况下,读语句处于事务内,分发需要考虑事务隔离级别,V82支持的三种隔离级别:可重复读,读提交,序列化。严格意义上这三种都不允许读语句分发,因为可能出现不可重复读或者读不到已提交的内容。但是如果事务内的语句就不分发的话,读写分离就失去大半意义了,因为无论是应用还是框架基本上都是用事务控制的,所以JDBC提供一个分发策略参数TransactionDispatchStrategy控制。 TransactionDispatchStrategy可以选择分发策略(性能优先,默认是2)1表示事务内的所有语句都只发主机,完全不分发备机; 2表示事务内遇到写语句之前的读语句,可以分发备机,遇到写语句之后就只发主机。
4.读写分离语句失败重发
JDBC支持切机本意就是指尽量让应用的语句不因为切机造成执行失败,让应用对切机无感知。对于单事务语句基本都可以重发成功,但并不是所有的语句都可以重发成功。 涉及连接会话上下文的以下几种情况会重发失败:
(1)游标:cursor,refcursor切机后全部丢失,重发不能成功。
(2)事务:切机后连接全部都断掉了,事务回退失败,不能重发。
(3)结果集遍历:和游标类似,重发不能成功。