引言

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

  • 垂直分库即基于业务层面,将不同业务数据存储到不同的数据库中。
  • 水平分表即把一个表的数据按照一定路由规则,路由到不同的数据库,通常采用按照某个字段如ID作为路由因子,路由到不同库。

架构演变

历史架构

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

 
历史架构

这种架构会有以下问题:

  • 自定义路由策略单一,只能通过某个单一分库因子路由到实际表
  • 自定义路由在当前数据库配置不足以支撑业务需要水平扩展时,需要在重新实现路由规则,并经过严格的业务和性能测试
  • 自定义路由在客户端水平扩展时,数据库连接数量是无法控制的,比如,一个客户端的数据库连接pool设置为100,如果我由两台扩展到4台,那么数据库服务器接入的连接数最大就可能由原来的200增加到400,可能会导致数据库服务器TCP连接数过多而内存不足或则宕机。

演变架构

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

 
当前架构部署图

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

Why MyCat

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

 
mycat架构设计图

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

  • 连接过多问题,可以通过MyCat统一管理所有的数据源,更灵活的支持客户端水平扩展,通过mycat统一管理连接池连接数量
  • 独创的ER关系分片,解决E-R分片难处理问题,存在关联关系的父子表在数据插入的过程中,子表会被MyCat路由到其相关父表记录的节点上,从而父子表的Join查询可以下推到各个数据库节点上完成,这是最高效的跨节点Join处理技术,也是MyCat首创。
  • 采用全局分片技术,每个节点同时并发插入和更新数据,每个节点都可以读取数据,提升读性能的同时,也解决跨节点Join的效率。
  • 通过人工智能的catlet支持跨分片复杂SQL实现以及存储过程支持等。

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

Why HaProxy

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

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

 
MyCat官方推荐高可用架构

阿里云SLB碰到的坑

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

  • 第一个要说的就是我们为什么没采取阿里云的SLB直接代理MyCat集群,刚开始设计架构的时候用的就是基于SLB做负载均衡,在项目运行一段时间后,发现MySql数据库服务器的TCP连接源源不断的增加,并且不会自我释放连接。经过研究发现,MyCat在接收到SLB发送的健康检查心跳的指令时,会把非mysql协议的指令直接发送给真实的mysql服务器,会建立大量MsqlIO连接,而mysql数据库无法识别这些指令就导致数据库连接泄露,这也算是Mycat的一个Bug,目前Mycat还没有解决该问题。

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

  • 我们用了MyCat官方推荐的基于多台HaProxy+KeepAlived+MyCat的集群架构,但是阿里云的上ECS服务器跟我们自己的虚拟机不一样,它不支持浮动IP的,所以我们无法使用keepalived方案,虽然现在可以利用阿里云VIP解决这个问题,但是阿里云服务器上keepalived只能设置单播,且要做当主库宕机恢复后,容易出现IP漂移的问题,所以我们也放弃了这个方案。

当前问题和解决方案

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

  • 方案一:基于Spring技术,自己开发了一套数据库客户端软负载的中间件,可以在数据库连接池中获取连接时,通过负载均衡器从动态数据源集合对象中后去一个数据源,并在初始化时启动一个线程监控所有mycat连接,定时进行健康检查,并根据结果更新负载均衡数据源集合对象中的数据源,其原理图如下:

     
    自定义数据库软负载原理图
  • 方案二:基于MySql Connector/J java连接器的LoadBalancing协议,进行负载均衡。
    下面我们着重介绍Mysql Connector的loadbalancing协议

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)

  • 当autocommit为false时,在事务的边界方法执行后,比如commit、rollback,将会触发BalanceStrategy从host列表中重新选择新的链接。
  • 当链接上发生Exception时,比如socket异常,将会导致重新选择链接。
  • 当autocommit为true时,当链接上执行“loadBalanceAutoCommitStatementThreshold”个statements后(Queries或者updates等),将会导致重新选择链接,默认为0表示“粘性链接,不重新选择链接”。(这是负载均衡的一种补偿措施)

方案选择

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

  • 方案一自定义软负载是自己实现的,功能单一,负载策略只有轮询,而且健康检查在很长一段时间出现连接泄露的问题,稳定性不够好,还需要做一些优化和测试进行打磨;
  • 方案二是基于mysql的java连接驱动做的负载均衡,是官方提供的方案,稳定性和可用性更高,而且我们在经过很长一段时间的压测和容错性测试,发现其性能很优越,负载均衡策略也更丰富,使用过程更简单。

值得注意的是其中的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

  • useUnicode=true&characterEncoding=utf-8:指定字符的编码、解码格式。
  • zerodatetimebehavior=converttonull:JAVA连接MySQL数据库,在操作各项值均为为0(或者有0不正确的数据)的timestamp等(日期为0000-00-00。。。。)类型时不能正确处理,而是默认抛出一个异常,比如所见的:java.sql.SQLException: Cannot convert value '0000-00-00 00:00:00' from column XX to TIMESTAMP
  • allowMultiQueries=true:可以允许一次执行多条sql(通过分号分割)

作者:愚行者
链接:https://www.jianshu.com/p/4c4641d4a566
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

基于mycat高可用方案——数据库负载的更多相关文章

  1. mycat高可用方案

    1.建议采用标准的mysql主从复制高可用配置并交付给mycat来完成后端mysql节点的主从自动切换. 2.mycat自身的高可用性 由HAproxy+Mycat集群+Mysql主从所组成的高可用性 ...

  2. Linux下"负载均衡+高可用"集群的考虑点 以及 高可用方案说明(Keepalive/Heartbeat)

    当下Linux运维技术越来越受到企业的关注和追捧, 在某些企业, 尤其是牵涉到电子商务和电子广告类的网站,通常会要求作负载均衡和高可用的Linux集群方案.那么如何实施Llinux集群架构,才能既有效 ...

  3. Mycat高可用解决方案一(mysql安装)

    Mycat高可用解决方案一(mysql安装) Mycat关键特性 关键特性 支持SQL92标准 支持MySQL.Oracle.DB2.SQL Server.PostgreSQL等DB的常见SQL语法 ...

  4. Mycat - 高可用与负载均衡实现,满满的干货!

    前言 开心一刻 和朋友去吃小龙虾,隔壁桌一个小女孩问妈妈:"妈妈,小龙虾回不了家,它妈妈会不会着急?" 她妈妈愣住了,我扒虾的手停下了,这么善良的问题,怎么下得了口.这是老板急忙过 ...

  5. MYSQL数据库高可用方案探究

    MySQL作为最关键的应用数据存储中心,如何保证MySQL服务的可靠性和持续性,是我们不得不细致考虑的一个问题.当master宕机的时候,我们如何保证数据尽可能的不丢失,如何保证快速的获知master ...

  6. MySQL数据库的高可用方案总结

    高可用架构对于互联网服务基本是标配,无论是应用服务还是数据库服务都需要做到高可用.虽然互联网服务号称7*24小时不间断服务,但多多少少有一些时候服务不可用,比如某些时候网页打不开,百度不能搜索或者无法 ...

  7. Dubbo入门到精通学习笔记(二十):MyCat在MySQL主从复制的基础上实现读写分离、MyCat 集群部署(HAProxy + MyCat)、MyCat 高可用负载均衡集群Keepalived

    文章目录 MyCat在MySQL主从复制的基础上实现读写分离 一.环境 二.依赖课程 三.MyCat 介绍 ( MyCat 官网:http://mycat.org.cn/ ) 四.MyCat 的安装 ...

  8. LVS+Keepalived搭建MyCAT高可用负载均衡集群

    LVS+Keepalived 介绍 LVS LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统.本项目在1998年5月由章文嵩博士成立,是中国 ...

  9. 基于GTID的Mysql-Mha高可用方案探索

    声明: 本篇文章内容整理来源于互联网以及本人自己的梳理总结,目的是从零到一的搭建起来mysql mha高可用架构. 一.软件概述 MHA(Master High Availability)目前在MyS ...

随机推荐

  1. IIS (安装SSL证书后) 实现 HTTP 自动跳转到 HTTPS

    IIS 里 安装好 SSL 证书后,如何实现 在浏览器里录入 http://www.xxx.com,会自动跳转到 https://www.xxx.com 呢. 首先,下载并安装 IIS 扩展: URL ...

  2. js实现带上传进度的文件上传

    //获取文件筐的文件集合 var files = document.getElementById("file1").files; //创建FormData对象 相当于参数集合 存储 ...

  3. SaaS技术栈的走势

    本地部署时代 在软件还是“本地部署(on-premise)”的时候,SaaS的版图被大型玩家把持着,几乎所有的垂直领域(营销.支持.销售.人力)都被微软.SAP等大公司的解决方案占据.那时候的用户并没 ...

  4. 我是这样搞懂一个神奇的BUG

    摘要: 通过分析用户的行为,才想得到为什么会出现这种情况! 前两天在BearyChat收到这样的一个报警消息: 409 ?Conflict ? 平时很少遇到这样的错误,貌似很严重的样子,吓得我赶紧查看 ...

  5. DOCTYPE声明作用?标准模式与兼容模式?

    <!DOCTYPE>文档声明是用来告诉浏览器使用哪种DTD,一般放在(X)HTML文档开头声明,用以告诉其他人这个文档的类型风格:DTD(文档类型定义)是一组机器可读的规则,它们指示(X) ...

  6. 李飞飞确认将离职!谷歌云AI总帅换人,卡耐基·梅隆老教授接棒

    https://mp.weixin.qq.com/s/i1uwZALu1BcOq0jAMvPdBw 看点:李飞飞正式回归斯坦福,新任谷歌云AI总帅还是个教授,不过这次是全职. 智东西9月11日凌晨消息 ...

  7. 如何制作微信动态表情包 GIF制作工具哪个好

    表情包已经成为我们生活聊天中必不可少的一部分,但是如何制作微信动态表情包呢?自己制作的表情包更加独有个性,今天小编带大家看一波原创表情包的制作方法吧! 使用工具:电脑 操作方法: 1.首先在手机上也是 ...

  8. Android 滑动定位+吸附悬停效果实现

    在前两篇文章中,分别介绍了tablayout+scrollview 和 tablayout+recyclerview 实现的滑动定位的功能,文章链接: Android 实现锚点定位 Android t ...

  9. 「破解」Xposed强

    「破解」Xposed强 Hook Hook Hook! 两张图片,第一张是我的微信截图,第二张是我从微信Hook出的一些类名. 一段代码,Hook这些类名出来的源码. 知道这些我们能干嘛,当然是分析( ...

  10. git上传中的排除的配置文件, git实际的操作代码;

    git上传中的排除的配置文件: git实际的操作 在主目录建立.gitignore文件并输入以下保存: *.class #package file *.war *.ear #kdiff3 ignore ...