2. jdbc中间件sharding,这个和协议差不多,就是把服务实现为了一个中间件,好处是协议损失时间可以补回来,坏处是只有java可以使用,开源的有当当的jdbc sharding
3.mysql的ndbcluster和fabric,这是mysql 引擎层面做的sharding,直接用mysql的协议层和计划生成,这个做的好处是原生的协议层都是百分百支持,事务用mysql xa支持也算马马虎虎,坏处是单机引擎,不能支持大数据的sql
这3种,被统称为“share-nothing”的数据库sharing模式,share-nothing很容易理解,就是每个被sharding的数据库之间没有共享任何数据。这种模式的缺点,主要就是:
1. sharding的时候必须带sharding key,或者不带sharding key就全表扫描
2. 必须预设sharding key,但是sharding key设计是很考验架构师对体系了解的,比如这里的sharding key 会和事务息息相关
3. 对事务的支持仅限于单库,跨库事务要走二阶段,不支持read repeated和串行事务
4. 扩容意味着sharding key计算方式改变,需要停写
5. 调度角度来看,proxy部分cpu是很浪费的,流量大的时候容易变成瓶颈,流量小的时候cpu都浪费了
当然share nothing的模式也是有谷歌参与一腿的,那就是youtube的vitess,他用设计和取舍很好规避了上述的很多问题:
1. proxy 转换两次协议的浪费,vitess直接用grpc来做sql转发,这样不用自己转mysql协议
2. 扩容难题,vitess用的是范围sharding,也就是拟定每个分库key值上下限,扩容只涉及三个库,扩容一般是split模式,不需要伤经动骨
3. 语句支持,这个基本上能上层做的优化大家都有做,不赘述
4. 运维和调度模式简单,部署模式用了 kubernetes的模型,proxy被暴露为service,后面多个服务都变成pod,把部署扔给了一个好的调度模型,而且里面mysql单例是启动在docker上,再把存储挂载在普通硬盘上,实现了存储和进程基本分离
5. 事务不赘述,基本上其他几个能不能做是意愿问题,不是设计问题
6. 自建二级索引,方便查找,方便不用先定sharding key
所以没有把vitess归类在上面任意一个层里,它比较独立,看起来vitess是不是完美了?并不是,毕竟share nothing模式的思路一开始就是有问题的,等我接下来细细分析为何vitess这个设计这么牛逼的项目 在谷歌基本上属于边缘甚至被淘汰项目
不一定需要自己开发。Shard层可以位于:1、DAO层:一般需要自行开发,可以灵活定制
2、ORM层:比如guzz、Hibernate Shard
3、JDBC API层:比较难,有一个商业产品dbShards
4、应用服务器与数据库之间通过代理实现:MySQL Proxy、amoeba.....
一 背景
当数据库中的数据量越来越大时,不论是读还是写,压力都会变得越来越大。采用MySQL
Replication多master多slave方案,在上层做负载均衡,虽然能够一定程度上缓解压力。但是当一张表中的数据变得非常庞大时,压力还是
非常大的。试想,如果一张表中的数据量达到了千万甚至上亿级别的时候,不管是建索引,优化缓存等,都会面临巨大的性能压力。
二 定义
数据sharding,也称作数据切分,或分区。是指通过某种条件,把同一个数据库中的数据分散到多个数据库或多台机器上,以减小单台机器压力。
三 分类
数据分区根据切分规则,可以分为两类:
1、垂直切分
数据的垂直切分,也可以称之为纵向切分。将数据库想象成为由很多个一大块一大块的“数据块”(表)组成,我们垂直的将这些“数据块”切开,然后将他们分散
到多台数据库主机上面。这样的切分方法就是一个垂直(纵向)的数据切分。以表为单位,把不同的表分散到不同的数据库或主机上。规则简单,实施方便,适合业
务之间耦合度低的系统。
Sharding详解" title="MySQL Sharding详解" height="373" width="553">
垂直切分的优点
(1)数据库的拆分简单明了,拆分规则明确
(2)应用程序模块清晰明确,整合容易
(3)数据维护方便易行,容易定位
垂直切分的缺点
(1)部分表关联无法在数据库级别完成,需要在程序中完成
(2)对于访问极其频繁且数据量超大的表仍然存在性能平静,不一定能满足要求
(3)事务处理相对更为复杂
(4) 切分达到一定程度之后,扩展性会遇到限制
(5)过读切分可能会带来系统过渡复杂而难以维护。
2、水平切分
一般来说,简单的水平切分主要是将某个访问极其平凡的表再按照某个字段的某种规则来分散到多个表之中,每个表中包含一部分数据。以行为单位,将同一个表中的数据按照某种条件拆分到不同的数据库或主机上。相对复杂,适合单表巨大的系统。
Sharding详解" title="MySQL Sharding详解" height="372" width="553">
水平切分的优点
(1)表关联基本能够在数据库端全部完成
(2)不会存在某些超大型数据量和高负载的表遇到瓶颈的问题
(3)应用程序端整体架构改动相对较少
(4)事务处理相对简单
(5)只要切分规则能够定义好,基本上较难遇到扩展性限制
水平切分的缺点
(1)切分规则相对更为复杂,很难抽象出一个能够满足整个数据库的切分规则
(2)后期数据的维护难度有所增加,人为手工定位数据更困难
(3)应用系统各模块耦合度较高,可能会对后面数据的迁移拆分造成一定的困难。
3、联合切分
实际的应用场景中,除了那些负载并不是太大,业务逻辑也相对较简单的系统可以通过上面两种切分方法之一来解决扩展性问题之外,恐怕其他大部分业务逻辑稍微
复杂一点,系统负载大一些的系统,都无法通过上面任何一种数据的切分方法来实现较好的扩展性,而需要将上述两种切分方法结合使用,不同的场景使用不同的切
分方法。
Sharding详解" title="MySQL Sharding详解" height="480" width="342">
联合切分的优点
(1)可以充分利用垂直切分和水平切分各自的优势而避免各自的缺陷
(2)让系统扩展性得到最大化提升
联合切分的缺点
(1)数据库系统架构比较复杂,维护难度更大
(2)应用程序架构也相对更复杂
四 实现方案
现在 Sharding 相关的软件实现其实不少,基于数据库层、DAO 层、不同语言下也都不乏案例。限于篇幅,此处只作一下简要的介绍。
1、 Mysql Proxy + HASCALE
一套比较有潜力的方案。其中MySQL Proxy 是用 Lua 脚本实现的,介于客户端与服务器端之间,扮演 Proxy
的角色,提供查询分析、失败接管、查询过滤、调整等功能。目前的 0.6 版本还做不到读、写分离。HSCALE 则是针对 MySQL Proxy 插件,也是用
Lua 实现的,对 Sharding 过程简化了许多。需要指出的是,MySQL Proxy 与 HSCALE
各自会带来一定的开销,但这个开销与集中式数据处理方式单条查询的开销还是要小的。
MySQLProxy是MySQL官方提供的一个数据库代理层产品,和MySQLServer一样,同样是一个基于GPL开源协议的开源产品。可用来监视、分析或者传输他们之间的通讯信息。他的灵活性允许你最大限度的使用它,目前具备的功能主要有连接路由,Query分析,Query过滤和修改,负载均衡,以及基本的HA机制等。
实际上,MySQLProxy本身并不具有上述所有的这些功能,而是提供了实现上述功能的基础。要实现这些功能,还需要通过我们自行编写LUA脚本来实现。
MySQLProxy实际上是在客户端请求与MySQLServer之间建立了一个连接池。所有客户端请求都是发向MySQLProxy,然后经由MySQLProxy进行相应的分析,判断出是读 *** 作还是写 *** 作,分发至对应的MySQLServer上。对于多节点Slave集群,也可以起做到负载均衡的效果。以下是MySQLProxy的基本架构图:
Sharding详解" title="MySQL Sharding详解" height="480" width="420">
通过上面的架构简图,我们可以很清晰的看出MySQLProxy在实际应用中所处的位置,以及能做的基本事情。关于MySQLProxy更为详细的实施细则在MySQL官方文档中有非常详细的介绍和示例,感兴趣的读者朋友可以直接从MySQL官方网站免费下载或者在线阅读,我这里就不累述浪费纸张了。
http://forge.mysql.com/wiki/MySQL_Proxy
2、 Hibernate Shards
这是 Google 技术团队贡献的项目(http://www.hibernate.org/414.html),该项目是在对Google 财务系统数据
Sharding 过程中诞生的。因为是在框架层实现的,所以有其独特的特性:标准的 Hibernate 编程模型,会用 Hibernate
就能搞定,技术成本较低相对d性的 Sharding 策略以及支持虚拟 Shard 等。
3、 Spock Proxy
这也是在实际需求中产生的一个开源项目,基于Mysql Proxy扩展。Spock(http://www.spock.com/)是一个人员查找的 Web
2.0 网站。通过对自己的单一 DB 进行有效 Sharding化 而产生了Spock
Proxy(http://spockproxy.sourceforge.net/ ) 项目,Spock Proxy 算得上 MySQL Proxy
的一个分支,提供基于范围的 Sharding 机制。Spock 是基于 Rails 的,所以Spock Proxy 也是基于 Rails 构建,关注 ROR
的朋友不应错过这个项目。
http://spockproxy.sourceforge.net/
4、 Amoeba for MySQL
Amoeba是一个基于Java开发的,专注于解决分布式数据库数据源整合Proxy程序的开源框架,基于GPL3开源协议。目前,Amoeba已经具有Query路由,Query过滤,读写分离,负载均衡以及HA机制等相关内容。
Amoeba 主要解决的以下几个问题:
(1)数据切分后复杂数据源整合
(2)提供数据切分规则并降低数据切分规则给数据库带来的影响
(3)降低数据库与客户端的连接数
(4)读写分离路由。
我们可以看出,Amoeba所做的事情,正好就是我们通过数据切分来提升数据库的扩展性所需要的。
Amoeba并不是一个代理层的Proxy程序,而是一个开发数据库代理层Proxy程序的开发框架,目前基于Amoeba所开发的Proxy程序有AmoebaForMySQL和AmoebaForAladin两个。
AmoebaForMySQL主要是专门针对MySQL数据库的解决方案,前端应用程序请求的协议以及后端连接的数据源数据库都必须是MySQL。对于客户端的任何应用程序来说,AmoebaForMySQL和一个MySQL数据库没有什么区别,任何使用MySQL协议的客户端请求,都可以被AmoebaForMySQL解析并进行相应的处理。下如可以告诉我们AmoebaForMySQL的架构信息(出自Amoeba开发者博客):
Sharding详解" title="MySQL Sharding详解" height="480" width="384">
AmoebaForAladin则是一个适用更为广泛,功能更为强大的Proxy程序。他可以同时连接不同数据库的数据源为前端应用程序提供服务,但是仅仅接受符合MySQL协议的客户端应用程序请求。也就是说,只要前端应用程序通过MySQL协议连接上来之后,AmoebaForAladin会自动分析Query语句,根据Query语句中所请求的数据来自动识别出该所Query的数据源是在什么类型数据库的哪一个物理主机上面。下图展示了AmoebaForAladin的架构细节(出自Amoeba开发者博客):
Sharding详解" title="MySQL Sharding详解" height="480" width="384">
咋一看,两者好像完全一样嘛。细看之后,才会发现两者主要的区别仅在于通过MySQLProtocalAdapter处理之后,根据分析结果判断出数据源数据库,然后选择特定的JDBC驱动和相应协议连接后端数据库。
其实通过上面两个架构图大家可能也已经发现了Amoeba的特点了,他仅仅只是一个开发框架,我们除了选择他已经提供的ForMySQL和ForAladin这两款产品之外,还可以基于自身的需求进行相应的二次开发,得到更适应我们自己应用特点的Proxy程序。
当对于使用MySQL数据库来说,不论是AmoebaForMySQL还是AmoebaForAladin都可以很好的使用。当然,考虑到任何一个系统越是复杂,其性能肯定就会有一定的损失,维护成本自然也会相对更高一些。所以,对于仅仅需要使用MySQL数据库的时候,我还是建议使用AmoebaForMySQL。
AmoebaForMySQL的使用非常简单,所有的配置文件都是标准的XML文件,总共有四个配置文件。分别为:
(1)amoeba.xml:主配置文件,配置所有数据源以及Amoeba自身的参数设置
(2)rule.xml:配置所有Query路由规则的信息
(3)functionMap.xml:配置用于解析Query中的函数所对应的Java实现类
(4)rullFunctionMap.xml:配置路由规则中需要使用到的特定函数的实现类
如果您的规则不是太复杂,基本上仅需要使用到上面四个配置文件中的前面两个就可完成所有工作。Proxy程序常用的功能如读写分离,负载均衡等配置都在amoeba.xml中进行。此外,Amoeba已经支持了实现数据的垂直切分和水平切分的自动路由,路由规则可以在rule.xml进行设置。
目前Amoeba少有欠缺的主要就是其在线管理功能以及对事务的支持了,曾经在与相关开发者的沟通过程中提出过相关的建议,希望能够提供一个可以进行在线维护管理的命令行管理工具,方便在线维护使用,得到的反馈是管理专门的管理模块已经纳入开发日程了。另外在事务支持方面暂时还是Amoeba无法做到的,即使客户端应用在提交给Amoeba的请求是包含事务信息的,Amoeba也会忽略事务相关信息。当然,在经过不断完善之后,我相信事务支持肯定是Amoeba重点考虑增加的feature。
关于Amoeba更为详细的使用方法读者朋友可以通过Amoeba开发者博客(http://amoeba.sf.net)上面提供的使用手册获取,这里就不再细述了。
案例(http://pengranxiang.iteye.com/blog/1145342)
*** 作文档(http://docs.hexnova.com/amoeba/chap-getting-started.html)
5、 HiveDB
和前面的MySQLProxy以及Amoeba一样,HiveDB同样是一个基于Java针对MySQL数据库的提供数据切分及整合的开源框架,只是目前的HiveDB仅仅支持数据的水平切分。主要解决大数据量下数据库的扩展性及数据的高性能访问问题,同时支持数据的冗余及基本的HA机制。
HiveDB的实现机制与MySQLProxy和Amoeba有一定的差异,他并不是借助MySQL的Replication功能来实现数据的冗余,而是自行实现了数据冗余机制,而其底层主要是基于HibernateShards来实现的数据切分工作。
在HiveDB中,通过用户自定义的各种Partitionkeys(其实就是制定数据切分规则),将数据分散到多个MySQLServer中。在访问的时候,在运行Query请求的时候,会自动分析过滤条件,并行从多个MySQLServer中读取数据,并合并结果集返回给客户端应用程序。
单纯从功能方面来讲,HiveDB可能并不如MySQLProxy和Amoeba那样强大,但是其数据切分的思路与前面二者并无本质差异。此外,HiveDB并不仅仅只是一个开源爱好者所共享的内容,而是存在商业公司支持的开源项目。
下面是HiveDB官方网站上面一章图片,描述了HiveDB如何来组织数据的基本信息,虽然不能详细的表现出太多架构方面的信息,但是也基本可以展示出其在数据切分方面独特的一面了。
Sharding详解" title="MySQL Sharding详解" height="471" width="553">
http://www.hivedb.org/
6、 DataFabric
application-level sharding
master/slave replication
https://github.com/bpot/data_fabric
7、PL/Proxy
前面几个都是针对MySQL 的 Sharding 方案,PL/Proxy 则是针对 PostgreSQL 的,设计思想类似 Teradata 的
Hash 机制,数据存储对客户端是透明的,客户请求发送到 PL/Proxy 后,由这里分布式存储过程调用,统一分发。 PL/Proxy
的设计初衷就是在这一层充当”数据总线”的职责,所以,当数据吞吐量支撑不住的时候,只需要增加更多的 PL/Proxy 服务器即可。大名鼎鼎的 Skype 用的就是
PL/Proxy 的解决方案。
8、Pyshards
这是个基于Python的解决方案。该工具的设计目标还有个 Re-balancing 在里面,这倒是个比较激进的想法。目前只支持 MySQL
数据库。
http://code.google.com/p/pyshards/wiki/Pyshards
9、其他实现数据切分及整合的解决方案
除了上面介绍的几个数据切分及整合的整体解决方案之外,还存在很多其他同样提供了数据切分与整合的解决方案。如基于MySQLProxy的基础上做了进一步扩展的HSCALE,通过Rails构建的SpockProxy,以及基于Pathon的Pyshards等等。
不管大家选择使用哪一种解决方案,总体设计思路基本上都不应该会有任何变化,那就是通过数据的垂直和水平切分,增强数据库的整体服务能力,让应用系统的整体扩展能力尽可能的提升,扩展方式尽可能的便捷。
只要我们通过中间层Proxy应用程序较好的解决了数据切分和数据源整合问题,那么数据库的线性扩展能力将很容易做到像我们的应用程序一样方便,只需要通过添加廉价的PCServer服务器,即可线性增加数据库集群的整体服务能力,让数据库不再轻易成为应用系统的性能瓶颈。
五 注意事项
下面我们所说的分区,主要是指水平分区。
1、在实施分区前,我们可以查看所安装版本的mysql是否支持分区:
mysql>show variables like "%partition%"
如果支持则会显示:
+-------------------+-------+
| Variable_name | Value |
+-------------------+-------+
| have_partitioning | YES |
+-------------------+-------+
2、分区适用于一个表的所有数据和索引,不能只对数据分区而不对索引分区,反之亦然,同时也不能只对表的一部分进行分区。
3、分区类型
(1)RANGE 分区:基于属于一个给定连续区间的列值,把多行分配给分区。
(2)LIST 分区:类似于按RANGE分区,区别在于LIST分区是基于列值匹配一个离散值集合中的某个值来进行选择。
(3)HASH分区:基于用户定义的表达式的返回值来进行选择的分区,该表达式使用将要插入到表中的这些行的列值进行计算(新浪微博采用的方案)。
(4)KEY 分区:类似于按HASH分区,区别在于KEY分区只支持计算一列或多列,且MySQL
服务器提供其自身的哈希函数。必须有一列或多列包含整数值。
无论使用何种类型的分区,分区总是在创建时就自动的顺序编号,且从0开始记录。当有一新行插入到一个分区表中时,就是使用这些分区编号来识别正确的分区。
4、MySQL提供了许多修改分区表的方式。添加、删除、重新定义、合并或拆分已经存在的分区是可能的。所有这些 *** 作都可以通过使用ALTER TABLE
命令的分区扩展来实现。
5、可以对已经存在的表进行分区,直接使用alter table命令即可。
Mysql-Proxy是一个处于你的client端和Mysql Server端之间的一个简单程序,它可以监测、分析和改变他们的通信。它使用灵活没有限制,常见的用途包括:负载平衡,故障、查询分析,查询过滤和修改等等。可以抽象成nginx与php-fpm的关系 本文介绍centos7.4上使用mysql-proxy
mysql-proxy 也支持读写分离/负载均衡等 可以详情可参考官方文档
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)