此文已由作者张镐薪授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。

SQL与NoSQL

目前,对于互联网海量数据的存储以及处理,按使用场景,分为OLTP(联机事务处理,比如即时交易,强调快速响应与处理)与OLAP(联机分析处理,比如BI,强调多维数据分析)。对于这些数据的存储,主要有两种解决方案,即基于SQL的关系型数据库,和NoSQL的非关系型数据库。
非关系型数据库在某些特定场景下有奇效,比如键值存储(redis,ROMA,Memcached)数据库应用在排行更新,会话保存,面向文档的数据库(mongoDB、couchDB)应用在日志记录,面向列的数据库(Cassandra、HBase)在博客中的应用。关系型数据库最大的问题在于速度与可扩展性上,而这些NoSQL数据库一般部署简单,支持扩展,而且速度极高。
但是,NoSQL目前还是只能做为关系型数据库在某些特定应用场景的补充,不能完全替代严谨规范的关系型数据库。

关系型数据库瓶颈

目前商用的数据库以及开源的数据库一般都不支持大规模自动扩展,单库上面存在着性能瓶颈。一般的,MySQL数据库单表超过1000W~2000W条记录时,性能就会有比较明显的下降。为了提升性能以及可以存储数据的量,我们需要分库分表。

分库分表

举个例子,假设我们原来的应用是为了客户完成下单,快递员接受并更新运单状态,客户可以随时查看运单状态的任务。一开始我们的数据库层架构设计(忽略其他部分,比如缓存、CDN等)可能是这样:但是很快地,我们发现,把所有的数据放在同一个库里面,随着业务的增长,数据量太大,响应时间变得越来越慢。业务需求已经承受不住了。我们首先做了垂直分片,按照业务模块,将数据库拆分成了快递员库,运单库和客户库来管理。再之后,我们发现运单单表有效数据量量级已经超过了2000W条,为了不影响TPS与QPS。我们需要把运单表做进一步的水平拆分。但是,水平分片后,像分片表关联这种操作,比如order by,group by还有join就不能通过数据库自己本身去完成了,因为每个分片库的数据都不是完整的。而且,跨分片事务(即分布式事务,分布式XA),比较难以实现。
拆分规则有很多种,需要根据具体业务决定。比如如果我们整体业务TPS小于单库可承受TPS,只是我们每天要产生2000W记录,而且这些记录要保存一周。我们可以按照日期分片,比如周一的数据保存到库1,之后以此类推。但是这样做的缺点很明显,同一天的写压力全都打到一个分片上,其他分片处于写空闲状态。即使整体业务TPS小于单库可承受TPS,这样的架构也不利于以后业务增长进行扩展。
我们还可以按照运单号对某一数字(分片个数)取模,让这些运单平均分布到每个后台分片库上。这样,我们可以保证同一时间所有的分片都是工作状态,没有资源浪费。但是,未来如果分片不够用了,扩容难还是个问题。
还有很多其它分片的规则(比如wang-jeekins哈希取模范围,扩容哈希范围,id字段范围等),在之后的MyCat中间件具体使用篇我会详细介绍,并给出一些原创的可行的分片方案。

谁来分库分表

实现这种分库分表可以有多种思路,看上面的架构图,我们可以:

  • 在数据库层做手脚

  • 在应用层做手脚

  • 在应用层与数据库层添加数据库路由中间件(相当于代理)

    首先,在数据库层做手脚,需要数据库产品为开源的,而且修改MySQL和MariaDB之类的数据库需要相当专业的团队以及较高的成本,所以,一般项目初期不会考虑这种方式。

然后是在应用层做手脚,像Ibatis sharding, shark,TDDL等。他们实现分库分表的思路是很相似的:一般这些框架很轻量级,在应用端放一个jar。他们本身不一定都实现了动态配置,但是他们都可以和Disconf之类的动态配置中心结合,实现动态数据源与动态分片规则。首先,应用会访问附近的配置中心,配置中心会告诉这个应用应该去访问哪个数据库以及分片规则是什么。之后,应用会自己去访问数据库,并作分片和合并结果。
这样做的好处是:

  • 实现分片和结果聚合的压力分摊给了每一个应用

  • 根据应用业务场景开发对应的功能

  • 轻量级,代码少

  • 能最大发挥后台数据库的能力
    但是同时,也有它的局限性:

  • 依赖于额外的配置中心实现动态配置

  • 对应用代码有侵入性

  • 使应用处理变重

  • 应用出问题难以定位是哪里出了问题

  • 将业务开发与后台数据库分库分表管理耦合,难于开发管理

最后,是代理的方式:实现思路大概是,实现mysql协议栈,将自己伪装成一个mysql数据库,自己后台管理所有mysql实例。应用无感知,只当后台只是一个mysql实例。这个代理mysql实例,实现分库分表,结果合并等功能。
这种代理实现的好处在于:

  • 对应用没有侵入性

  • 压力打在中间件上

  • 统一管理后台数据库,能及时定位问题
    但是,他也有自己的缺陷,首先就是压力打在中间件上的话,可能不能发挥后台数据库最大的能力。由此,中间件需要做负载均衡集群,这要求中间件必须是无状态的。但是,这无疑增加了架构的复杂程度。目前,淘宝的高吞吐量业务还是在用TDDL类似的产品也是这个原因。
    这两种实现方式还都有共同的难以解决的问题,比如分布式事务这个问题,目前也没有非常完美的方案。还有,他们对于SQL都有限制(比如有的不支持DDL,大部分都不推荐使用大事务等)
    整体说来,项目初期使用代理这种实现方式还是利大于弊的,网上有很多开源产品,他们基本和淘宝的Amoeba和Cobar一脉相承。实际应用场景众多,较为可靠。本文即将介绍的MyCat也不例外。下一篇我们将更详细地介绍MyCat的背景 :-D

免费体验云安全(易盾)内容安全、验证码等服务

更多网易技术、产品、运营经验分享请点击

相关文章:
【推荐】 知物由学 | AI时代,那些黑客正在如何打磨他们的“利器”?(一)
【推荐】 Hive中文注释乱码解决方案
【推荐】 分布式存储系统可靠性系列三:设计模式

MyCat - 背景篇(1)的更多相关文章

  1. 数据库路由中间件MyCat - 背景篇(2)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. MyCat的前世今生 如前文所说,Amoeba.Cobar.MyCat等属于同宗一脉.若Amoeba能继续下 ...

  2. 数据库路由中间件MyCat - 使用篇(1)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 基本概念 直接介绍概念太枯燥了,还是拿个和背景篇相似的例子介绍 业务场景:客户完成下单,快递员接受并更新运单 ...

  3. MyCat - 使用篇

    Mycat水平拆分之十种分片规则: http://www.cnblogs.com/756623607-zhang/p/6656022.html 数据库路由中间件MyCat - 使用篇(5) 配置MyC ...

  4. 【C/C++】C语言嵌入式编程修炼·背景篇·软件架构篇·内存操作篇

    C 语言嵌入式系统编程修炼之一:背景篇 不同于一般形式的软件编程,嵌入式系统编程建立在特定的硬件平台上,势必要求其编程语言具备较强的硬件直接操作能力.无疑,汇编语言具备这样的特质.但是,归因于汇编语言 ...

  5. 数据库路由中间件MyCat - 源代码篇(15)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. public static void handle(String stmt, ServerConnectio ...

  6. 数据库路由中间件MyCat - 源代码篇(13)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 4.配置模块 4.2 schema.xml 接上一篇,接下来载入每个schema的配置(也就是每个MyCat ...

  7. 数据库路由中间件MyCat - 源代码篇(1)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 进入了源代码篇,我们先从整体入手,之后拿一个简单流程前端连接建立与认证作为例子,理清代码思路和设计模式.然后 ...

  8. 数据库路由中间件MyCat - 使用篇(4)

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 配置MyCat 3. 配置conf/rule.xml 1.5GA版本中的规则配置比较笨,2.0中优化了一些, ...

  9. 数据库路由中间件MyCat - 使用篇(3)下篇

    此文已由作者张镐薪授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 2. 配置conf/server.xml server.xml几乎保存了所有mycat需要的系统配置信息.其 ...

随机推荐

  1. 16-图片上传那些事 org.springframework.web.multipart.MultipartException: The current request is not a multipart request

    https://blog.csdn.net/u010974598/article/details/46458039 我曾尝试了: @RequestMapping(value="/user/r ...

  2. jquery-jsonp插件解决跨域问题

    用jquery-jsonp插件解决ajax跨域问题,既可以实现ajax同样的请求效果,而且server服务端的相关代码也不用做任何改变. 代码如下: var url="http://loca ...

  3. php的反射

    我们可以在PHP运行时,通过PHP的反射动态的获取类的方法.属性.参数等详细信息.   用途:插件的设计,文档的自动生成,扩充PHP语言. <?php class Person { const ...

  4. js 递归调用

    js递归调用 function fact(num) { ) { ; } else { ); } } 以下代码可导致出错: var anotherFact = fact; fact = null; al ...

  5. tcl&redis安装

    http://www.linuxfromscratch.org/blfs/view/cvs/general/tcl.html tcl http://redis.io/topics/quickstart

  6. Golang之Socket

    go创建socket很简单 package main import ( "fmt" "net" ) func main() { //服务器监听地址 fmt.Pr ...

  7. redis缓存设置和读取

    一/写入 <?php $redis = new Redis(); //实例化redis $redis->pconnect('); $redis->,'huahua'); //设置变量 ...

  8. 创建一个子进程---vfork

    子.父进程共享数据段与堆栈段 函数原型:pid_t vfork(void) 返回值:子进程中返回0,父进程中返回子进程ID,出错返回-1. 注意: vfork创建的进程是按先子进程后父进程的顺序执行的 ...

  9. for() 和$.each()的用法区别

    一.对于数组 var arr=['姚明','易建联','张继科']; $.each(arr,function(index,value){ document.write(index+"=&qu ...

  10. 构造函数constructor 与析构函数destructor(一)

    构造函数定义:构造函数c++中在创建对象时自动调用,用来初始化对象的特殊函数. (1)构造函数的名字必须与类的名字相同,不能有返回值,哪怕是void 也不行. (2)通常情况下构造函数应声明为公有函数 ...