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
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。