基于mycat高可用方案——数据库负载

2018-01-19  本文已影响785人  辣鸡简书_随意拉黑

引言

传统企业级应用一般采取单台数据库,吞吐所有应用的读写,随着互联网的高速发展,以及微服务架构越来越普及,往往采用分库分表来支撑高速增长的大量业务数据吞吐。分库分表主要有两种方式:水平分表和垂直分库。

架构演变

历史架构

我们改造之前,数据库层,基于业务做了垂直分库,某些数据量大的业务比如用户账户、账务、订单和优惠券等数据,都放到了同一个数据库实例并水平将数据拆分为十几个表,通过客户端自定义路由来做读写分离和数据命中。数据库架构如下图。


历史架构

这种架构会有以下问题:

演变架构

目前系统采用单台HaProxy负载多台mycat服务器,通过mycat分库分表,读写分离来管理和路由真实的多台mysql数据库RDS。其配置部署图如下:


当前架构部署图

下面就讲讲为什么选用当前这种架构部署方案。

Why MyCat

MyCat是一款优秀的开源分布式数据库中间件,架构设计图如下。

mycat架构设计图
具体实现原理这里就不多做赘述,它解决了哪些问题呢?

MyCat技术原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的SQL语句,首先对SQL语句做了一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此SQL发往后端的真实数据库,并将返回的结果做适当的处理,最终再返回给用户。

Why HaProxy

HAProxy是一个使用C语言编写的自由及开放源代码软件[1],其提供高可用性负载均衡,以及基于TCPHTTP的应用程序代理

HaProxy提供了高可用、负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机的高效可靠的解决方案,单纯从效率上讲比Nginx的负载均衡速度更优秀,关键是能兑Mysql数据库进行负载均衡。
MyCat官方推荐的高可用架构部署方案就是基于HaProxy做的负载均衡。

MyCat官方推荐高可用架构

阿里云SLB碰到的坑

我们在当前架构的实际应用中,踩过了不少的坑,可以说是一路泥泞。

如果谁有好的解决方案,请跟笔者联系。

当前问题和解决方案

基于上述现有数据库部署架构,我们肯定不难发现,如果单点HaProxy宕机,对我们整个生产环境系统来说,就是灾难性的雪崩,我们就做了一下解决方案:

Load Balancing协议与Failover协议

介绍loadbalancing协议之前我们先了解下Failover协议,loadbalancing协议就是基于Failover协议。

Failover协议

Failover协议是mysql的失效重连协议,即当客户端链接失效时,会尝试与其他host建立链接。其URL格式如下:

jdbc:mysql://[master-host]:[port],[slaves-host]:[port],.../[database]?[property=<value>]&[property=<value>]

master服务器需要位于hosts列表第一个,当创建一个connection时,mysql connector/J驱动会首先尝试和master host连接,如果出现异常,则依次和slaves中的host建立连接,直到成功为止;;即使与master的连接失效,但是mysql connector/J驱动并不会丢失master的特殊状态:比如它的访问模式、优先级等。当所有host都不可用,那么mysql connector/J驱动会继续轮询,直到次数达到阈值,通过属性retriesAllDown控制,默认120次,达到阈值仍然无法获取连接则跑出SQLException。
当master恢复后,mysql connector/J驱动又能自动的FallBack到master主机,基于这个特性,我们就能做一些故障容灾和自动恢复。

参见源码:(FailoverConnectionProxy)

Load Balancing(LB)协议

由于Failover协议没有load balance的特性,它读/写操作总是只发生在同一个host上,然而我们实际应用中,可能会出现‘replication’,‘多Master’的情况,比如我们mycat部署多台,需要负载均衡保证高可用,load balancing协议就应运而生了。LB协议可以将读/写负载到多个Mysql实例上,这些实例通常是‘replication’架构和集群架构。LB协议基于Failover协议,其URL格式为:

jdbc:mysql:loadbalance://[host]:[port],[host]:[port],...[/database]?[property=<value>]&[property=<value>]

mysql connector/J驱动创建的LoadBalancedConnection是一个逻辑链接,其内部持有一个物理链接列表,即与每个host建立一个Connection。url中的每个host都是平等的主host,当客户端获取连接时会有两种random(默认随机)bestResponseTime(最小响应时间)两种均衡策略,可以在参数** loadBalanceStrategy**中指定。

(参见源码:LoadBalancedConnectionProxy,BalanceStrategy,LoadBalancedConnection)

方案选择

两种方案我们都在开发、测试环境甚至生成环境做过很多对数据库读写的测试操作,对比后做了以下总结:

值得注意的是其中的autoReconnect、** autoReconnectForPools**这两个参数参数用于控制“重连”特性,即当一个session或者事务操作过程中,如果链接出现异常,driver不会跑出Exception而是尝试重新连接并继续执行,如果是非事务操作如查询,则该参数不会带来问题;如果是事务操作,在事务多个操作过程中发生重连,就有可能对session状态造成破坏,而导致数据不一致问题,即便开启autocommit=false仍然不能完全避免这个问题,事实上重连之后并不会rollback原来中断的事务,而是继续进行,参见【autoReconnect】。此参数选项将会在未来的版本中被移除,官方也建议禁用此特性。

总结

我们选择了基于msyql connector/J驱动的LB协议的数据库客户端高可用方案,其部署架构图如下:

基于数据库LB协议部署架构图

我建议数据库URL配置为一下格式:

jdbc:mysql:loadbalance://[host]:[port],[host]:[port],...[/database]?useUnicode=true&characterEncoding=utf-8&zerodatetimebehavior=converttonull&allowMultiQueries=true

上一篇 下一篇

猜你喜欢

热点阅读