前言
当应用规模越来越大时,数据往往是应用的瓶颈。如何正确的架构来扩展Mysql成了系统好坏的关键。
扩展方式
传统的解决方法有以下几种:
- 向上扩展(垂直扩展)
购买更强悍的机器。 - 向外扩展(水平扩展)
将任务分配到多台计算机 ,其扩展策略划分为3个部分:复制、拆分以及数据分片。- 垂直切分(拆分)
按功能(业务)将表进行分类,分布到不同的数据库上面。最大特点就是规则简单,实施也更为方便,尤其适合各业务之间的耦合度非常低,相互影响很小,业务逻辑非常清晰的系统。 - 水平切分(数据分片)
即按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中。
- 垂直切分(拆分)
几种典型的分片规则包括:
- 按照用户 ID 求模,将数据分散到不同的数据库,具有相同数据用户的数据都被分散到一个库中;
- 按照日期,将不同月甚至日的数据分散到不同的库中;
- 按照某个特定的字段求摸,或者根据特定范围段分散到不同的库中。
- 集群 (复制)
通过《mysql的复制及备份》实现mysql拓扑结构来负载均衡.
几种常见负载均衡的方法包括:
- 读写分离,即将特定的流量指向不同的机子
- 随机算法
- 轮循
- hash一致性
- 最少活跃数(通过响应时间,请求数判断,dubbo中有用)
- 。。。
- 向内扩展
大部分应用还会有很少或不需要的数据,这些数据可以被清理或归档。
高可用
高可用意味着更少的“宕机”时间。100%的可用性是不可能达到的。可用性的“9”规则是表示可用性目标最普遍的方法。“5个9”表示99.999%的正常可用时间。换句话说,每年只允许5min的宕机时间。
宕机原因
- 在运行环境中的问题,最普遍的原因是磁盘空间耗尽。
- 在性能问题中,最普遍的原因是运行了糟糕的SQL,但也不一定全是如此,有可能是服务器bug或错误的行为。
- 糟糕的Schema和索引设计是第二大影响性能的因素
- 复制功能导致的主备数据不一致。
- 数据丢失问题,通常是由于DROP TABLE误操作,并伴随缺少可用备份。
实现高可用性
首先,可以尝试避免导致宕机的原因来减少宕机时间。第二,尽量保证发生宕机时能尽快恢复。最常见的策略是在系统中制造冗余,并且具备故障转移能力。
- 数据冗余
通过《mysql的复制及备份》手段来数据冗余 - 故障转移
- 提升备库或切换角色,提升一台备库作为主库
- 虚拟IP地址或IP接管,将IP地址转移到另一台MySQL服务器上
中间件解决方案
解决mysql扩展与高可用的可能自己设计通过项目管理多个数据源的形式,但通过中单件的方式显的更优雅高效。这里主要讲的是MyCat解决方式。
MyCat原理
Mycat 的原理中最重要的一个动词是“拦截”,它拦截了用户发送过来的 SQL 语句,首先对 SQL 语句做了 一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此 SQL 发往后端的真实数据库, 并将返回的结果做适当的处理,最终再返回给用户。
MyCat架构
Mycat 是一个开源的分布式数据库系统,但是由于真正的数据库需要存储引擎,而Mycat并没有存储引擎,所以并不是完全意义的分布式数据库系统。
其通过以下配置与真正的存储引挚联系:
# 逻辑库
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100">
#逻辑表,使用rule1规则进行分片,对应后面节点为 dn1,dn2
<table name="t_node" dataNode="dn1,dn2" rule="rule1" />
</schema>
#dn1,dn2节点的真实配置分别指向localhost1虚拟数据库的db1,db2
<dataNode name="dn1" dataHost="localhost1" database="db1" />
<dataNode name="dn2" dataHost="localhost1" database="db2" />
#虚拟localhost1对应真实数据库配置
<dataHost name="localhost1" dbType="mysql" >
#心跳检测配置
<heartbeat>select user()</heartbeat>
#真实机子信息
<writeHost host="hostM1" url="localhost:3306" user="root"
password="123456">
</writeHost>
</dataHost>
扩展与高可用的实现
- 读写分离
<dataHost name="localhost1" dbType="mysql">
<heartbeat>select user()</heartbeat>
#写主机为hostM1
<writeHost host="hostM1" >
#读主机为hostS1
<readHost host="hostS1" />
</writeHost>
</dataHost>
- 主备切换
<dataHost name="localhost1" dbType="mysql">
<heartbeat>select user()</heartbeat>
#写主机为hostM1,如果hostM1挂了,会切换成hostS1
<writeHost host="hostM1" ></writeHost>
<writeHost host="hostS1" ></writeHost>
</dataHost>
- 分片规则
#以取模规则为例子
#id%3 == 0 dn1
#id%3 == 1 dn2
#id%3 == 2 dn1
<table name="t_node" dataNode="dn1,dn2" rule="mod-long" />
#取模规则,让id进行取模操作
<tableRule name="mod-long">
<rule>
<columns>id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
##取模算法
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
#取模算法的总分片数
<property name="count">3</property>
</function>
MyCat总结
- 遵守Mysql原生协议,跨语言,跨数据库的通用中间件代理。
- 基于心跳C的自动故障切换,支持读写分离,支持 MySQL
一双主多从,以及一主多从 有效管理数据源连接,基于数据分库,而不是分表的模式。 - 基于 NIO 实现,有效管理线程,高并发问题。
- 支持数据的多片自动路由与聚合,支持 sum , count , max 等常用的聚合函数。
- 支持2表 join,甚至基于 caltlet的多表 join。
- 支持通过全局表,ER 关系的分片策略,实现了高效的多表 join 查询。
- 支持多租户方案。 支持分布式事务(弱xa)
- 支持全局序列号,解决分布式下的主键生成问题。
- 分片规则丰富,插件化开发,易于扩展。
- 强大的 web,命令行监控。
- 支持前端作为 MySQL 通用代理,后端 JDBC 方式支持 Oracle、DB2、SQL Server 、 mongodb 、巨杉。
- 集群基于ZooKeeper 管理,在线升级,扩容,智能优化,大数据处理(2.0开发版)。
主要参考
《高性能Mysql》
《MyCat权威指南》