原文地址:http://kb.cnblogs.com/page/193670/html
双“11”最热门的话题是TB ,最近正好和阿里的一个朋友聊淘宝的技术架构,发现不少有意思的地方,分享一下他们的解析资料:前端
淘宝海量数据产品技术架构算法
数据产品的一个最大特色是数据的非实时写入,正由于如此,咱们能够认为,在必定的时间段内,整个系统的数据是只读的。这为咱们设计缓存奠基了很是重要的基础。数据库
图1 淘宝海量数据产品技术架构编程
按照数据的流向来划分,咱们把淘宝数据产品的技术架构分为五层(如图1所示),分别是数据源、计算层、存储层、查询层和产品层。位于架构顶端的是咱们的数据来源层,这里有淘宝主站的用户、店铺、商品和交易等数据库,还有用户的浏览、搜索等行为日志等。这一系列的数据是数据产品最原始的生命力所在。后端
在数据源层实时产生的数据,经过淘宝自主研发的数据传输组件DataX、DbSync和Timetunnel准实时地传输到一个有1500个节点的Hadoop集群上,这个集群咱们称之为“云梯”,是计算层的主要组成部分。在“云梯”上,咱们天天有大约40000个做业对1.5PB的原始数据按照产品需求进行不一样的MapReduce计算。这一计算过程一般都能在凌晨两点以前完成。相对于前端产品看到的数据,这里的计算结果极可能是一个处于中间状态的结果,这每每是在数据冗余与前端计算之间作了适当平衡的结果。浏览器
不得不提的是,一些对实效性要求很高的数据,例如针对搜索词的统计数据,咱们但愿能尽快推送到数据产品前端。这种需求再采用“云梯”来计算效率将是比较低的,为此咱们作了流式数据的实时计算平台,称之为“银河”。“银河”也是一个分布式系统,它接收来自TimeTunnel的实时消息,在内存中作实时计算,并把计算结果在尽量短的时间内刷新到NoSQL存储设备中,供前端产品调用。缓存
容易理解,“云梯”或者“银河”并不适合直接向产品提供实时的数据查询服务。这是由于,对于“云梯”来讲,它的定位只是作离线计算的,没法支持较高的性能和并发需求;而对于“银河”而言,尽管全部的代码都掌握在咱们手中,但要完整地将数据接收、实时计算、存储和查询等功能集成在一个分布式系统中,避免不了分层,最终仍然落到了目前的架构上。服务器
为此,咱们针对前端产品设计了专门的存储层。在这一层,咱们有基于MySQL的分布式关系型数据库集群MyFOX和基于HBase的NoSQL存储集群Prom,在后面的文字中,我将重点介绍这两个集群的实现原理。除此以外,其余第三方的模块也被咱们归入存储层的范畴。restful
存储层异构模块的增多,对前端产品的使用带来了挑战。为此,咱们设计了通用的数据中间层——glider——来屏蔽这个影响。glider以HTTP协议对外提供restful方式的接口。数据产品能够经过一个惟一的URL获取到它想要的数据。
以上是淘宝海量数据产品在技术架构方面的一个归纳性的介绍,接下来我将重点从四个方面阐述数据魔方设计上的特色。
关系型数据库仍然是王道
关系型数据库(RDBMS)自20世纪70年代提出以来,在工业生产中获得了普遍的使用。通过三十多年的长足发展,诞生了一批优秀的数据库软件,例如Oracle、MySQL、DB二、Sybase和SQL Server等。
图2 MyFOX中的数据增加曲线
尽管相对于非关系型数据库而言,关系型数据库在分区容忍性(Tolerance to Network Partitions)方面存在劣势,但因为它强大的语义表达能力以及数据之间的关系表达能力,在数据产品中仍然占据着不可替代的做用。
淘宝数据产品选择MySQL的MyISAM引擎做为底层的数据存储引擎。在此基础上,为了应对海量数据,咱们设计了分布式MySQL集群的查询代理层——MyFOX,使得分区对前端应用透明。
图3 MyFOX的数据查询过程
目前,存储在MyFOX中的统计结果数据已经达到10TB,占据着数据魔方总数据量的95%以上,而且正在以天天超过6亿的增量增加着(如图2所示)。这些数据被咱们近似均匀地分布到20个MySQL节点上,在查询时,经由MyFOX透明地对外服务(如图3所示)。
图4 MyFOX节点结构
值得一提的是,在MyFOX现有的20个节点中,并非全部节点都是“平等”的。通常而言,数据产品的用户更多地只关心“最近几天”的数据,越早的数据,越容易被冷落。为此,出于硬件成本考虑,咱们在这20个节点中分出了“热节点”和“冷节点”(如图4所示)。
顾名思义,“热节点”存放最新的、被访问频率较高的数据。对于这部分数据,咱们但愿能给用户提供尽量快的查询速度,因此在硬盘方面,咱们选择了每分钟15000转的SAS硬盘,按照一个节点两台机器来计算,单位数据的存储成本约为4.5W/TB。相对应地,“冷数据”咱们选择了每分钟7500转的SATA硬盘,单碟上可以存放更多的数据,存储成本约为1.6W/TB。
将冷热数据进行分离的另一个好处是能够有效提升内存磁盘比。从图4能够看出,“热节点”上单机只有24GB内存,而磁盘装满大约有1.8TB(300 * 12 * 0.5 / 1024),内存磁盘比约为4:300,远远低于MySQL服务器的一个合理值。内存磁盘比太低致使的后果是,总有一天,即便全部内存用完也存不下数据的索引了——这个时候,大量的查询请求都须要从磁盘中读取索引,效率大打折扣。
NoSQL是SQL的有益补充
在MyFOX出现以后,一切都看起来那么完美,开发人员甚至不会意识到MyFOX的存在,一条不用任何特殊修饰的SQL语句就能够知足需求。这个状态持续了很长一段时间,直到有一天,咱们碰到了传统的关系型数据库没法解决的问题——全属性选择器(如图5所示)。
图5 全属性选择器
这是一个很是典型的例子。为了说明问题,咱们仍然以关系型数据库的思路来描述。对于笔记本电脑这个类目,用户某一次查询所选择的过滤条件可能包括“笔记本尺寸”、“笔记本定位”、“硬盘容量”等一系列属性(字段),而且在每一个可能用在过滤条件的属性上,属性值的分布是极不均匀的。在图5中咱们能够看到,笔记本电脑的尺寸这一属性有着10个枚举值,而“蓝牙功能”这个属性值是个布尔值,数据的筛选性很是差。
在用户所选择的过滤条件不肯定的状况下,解决全属性问题的思路有两个:一个是穷举全部可能的过滤条件组合,在“云梯”上进行预先计算,存入数据库供查询;另外一个是存储原始数据,在用户查询时根据过滤条件筛选出相应的记录进行现场计算。很明显,因为过滤条件的排列组合几乎是没法穷举的,第一种方案在现实中是不可取的;而第二种方案中,原始数据存储在什么地方?若是仍然用关系型数据库,那么你打算怎样为这个表创建索引?
这一系列问题把咱们引到了“建立定制化的存储、现场计算并提供查询服务的引擎”的思路上来,这就是Prometheus(如图6所示)。
图6 Prom的存储结构
从图6能够看出,咱们选择了HBase做为Prom的底层存储引擎。之因此选择HBase,主要是由于它是创建在HDFS之上的,而且对于MapReduce有良好的编程接口。尽管Prom是一个通用的、解决共性问题的服务框架,但在这里,咱们仍然以全属性选择为例,来讲明Prom的工做原理。这里的原始数据是前一天在淘宝上的交易明细,在HBase集群中,咱们以属性对(属性与属性值的组合)做为row-key进行存储。而row-key对应的值,咱们设计了两个column-family,即存放交易ID列表的index字段和原始交易明细的data字段。在存储的时候,咱们有意识地让每一个字段中的每个元素都是定长的,这是为了支持经过偏移量快速地找到相应记录,避免复杂的查找算法和磁盘的大量随机读取请求。
图7 Prom查询过程
图7用一个典型的例子描述的Prom在提供查询服务时的工做原理,限于篇幅,这里不作详细描述。值得一提的是,Prom支持的计算并不只限于求和SUM运算,统计意义上的经常使用计算都是支持的。在现场计算方面,咱们对HBase进行了扩展,Prom要求每一个节点返回的数据是已经通过“本地计算”的局部最优解,最终的全局最优解只是各个节点返回的局部最优解的一个简单汇总。很显然,这样的设计思路是要充分利用各个节点的并行计算能力,而且避免大量明细数据的网络传输开销。
用中间层隔离先后端
上文提到过,MyFOX和Prom为数据产品的不一样需求提供了数据存储和底层查询的解决方案,但随之而来的问题是,各类异构的存储模块给前端产品的使用带来了很大的挑战。而且,前端产品的一个请求所须要的数据每每不可能只从一个模块获取。
举个例子,咱们要在数据魔方中看昨天作热销的商品,首先从MyFOX中拿到一个热销排行榜的数据,但这里的“商品”只是一个ID,并无ID所对应的商品描述、图片等数据。这个时候咱们要从淘宝主站提供的接口中去获取这些数据,而后一一对应到热销排行榜中,最终呈现给用户。
图8 glider的技术架构
有经验的读者必定能够想到,从本质上来说,这就是广义上的异构“表”之间的JOIN操做。那么,谁来负责这个事情呢?很容易想到,在存储层与前端产品之间增长一个中间层,它负责各个异构“表”之间的数据JOIN和UNION等计算,而且隔离前端产品和后端存储,提供统一的数据查询服务。这个中间层就是glider(如图8所示)。
缓存是系统化的工程
除了起到隔离先后端以及异构“表”之间的数据整合的做用以外,glider的另一个不容忽视的做用即是缓存管理。上文提到过,在特定的时间段内,咱们认为数据产品中的数据是只读的,这是利用缓存来提升性能的理论基础。
在图8中咱们看到,glider中存在两层缓存,分别是基于各个异构“表”(datasource)的二级缓存和整合以后基于独立请求的一级缓存。除此以外,各个异构“表”内部可能还存在本身的缓存机制。细心的读者必定注意到了图3中MyFOX的缓存设计,咱们没有选择对汇总计算后的最终结果进行缓存,而是针对每一个分片进行缓存,其目的在于提升缓存的命中率,而且下降数据的冗余度。
大量使用缓存的最大问题就是数据一致性问题。如何保证底层数据的变化在尽量短的时间内体现给最终用户呢?这必定是一个系统化的工程,尤为对于分层较多的系统来讲。
图9 缓存控制体系
图9向咱们展现了数据魔方在缓存控制方面的设计思路。用户的请求中必定是带了缓存控制的“命令”的,这包括URL中的query string,和HTTP头中的“If-None-Match”信息。而且,这个缓存控制“命令”必定会通过层层传递,最终传递到底层存储的异构“表”模块。各异构“表”除了返回各自的数据以外,还会返回各自的数据缓存过时时间(ttl),而glider最终输出的过时时间是各个异构“表”过时时间的最小值。这一过时时间也必定是从底层存储层层传递,最终经过HTTP头返回给用户浏览器的。
缓存系统不得不考虑的另外一个问题是缓存穿透与失效时的雪崩效应。缓存穿透是指查询一个必定不存在的数据,因为缓存是不命中时被动写的,而且出于容错考虑,若是从存储层查不到数据则不写入缓存,这将致使这个不存在的数据每次请求都要到存储层去查询,失去了缓存的意义。
有不少种方法能够有效地解决缓存穿透问题,最多见的则是采用布隆过滤器,将全部可能存在的数据哈希到一个足够大的bitmap中,一个必定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。在数据魔方里,咱们采用了一个更为简单粗暴的方法,若是一个查询返回的数据为空(无论是数据不存在,仍是系统故障),咱们仍然把这个空结果进行缓存,但它的过时时间会很短,最长不超过五分钟。
缓存失效时的雪崩效应对底层系统的冲击很是可怕。遗憾的是,这个问题目前并无很完美的解决方案。大多数系统设计者考虑用加锁或者队列的方式保证缓存的单线程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。在数据魔方中,咱们设计的缓存过时机制理论上可以将各个客户端的数据失效时间均匀地分布在时间轴上,必定程度上可以避免缓存同时失效带来的雪崩效应。
结束语
正是基于本文所描述的架构特色,数据魔方目前已经可以提供压缩前80TB的数据存储空间,数据中间层glider支持天天4000万的查询请求,平均响应时间在28毫秒(6月1日数据),足以知足将来一段时间内的业务增加需求。
尽管如此,整个系统中仍然存在不少不完善的地方。一个典型的例子莫过于各个分层之间使用短链接模式的HTTP协议进行通讯。这样的策略直接致使在流量高峰期单机的TCP链接数很是高。因此说,一个良好的架构当然可以在很大程度上下降开发和维护的成本,但它自身必定是随着数据量和流量的变化而不断变化的。我相信,过不了几年,淘宝数据产品的技术架构必定会是另外的样子。
其余文章摘要
【1】海量数据领域涵盖分布式数据库、分布式存储、数据实时计算、分布式计算等多个技术方向。
对于海量数据处理,从数据库层面来说无非就是两点:一、压力如何分摊,分摊的目的就是为了把集中式变为分布式。二、采用多种的存储方案,针对不一样的业务数据,不一样的数据特色,采用RDBMS或采用KV Store,选择不一样数据库软件,使用集中式或分布式存储,或者是其余的一些存储方案。
【2】将数据库进行拆分,包括水平拆分和垂直拆分。
水平拆分主要解决两个问题:一、底层存储的无关性。二、经过线性的去增长机器,支持数据量以及访问请求包括TPS(Transaction Per Second)、QPS(Query Per Second)的压力增加。其方式如把一张大数据表按必定的方式拆分到不一样的数据库服务器上。
海量数据从集中式走向分布式,可能涉及跨多个IDC容灾备份特性。
【3】阿里巴巴的数据对不一样地域数据的处理方法。
由三个产品密切配合解决:是Erosa、Eromanga和Otter。
Erosa作MySQL(或其余数据库库)的Bin-Log时时解析,解析后放到Eromanga。Eromanga是增量数据的发布订阅的产品。Erosa产生了时时变动的数据发布到Eromanga。而后各个业务端(搜索引擎、数据仓库或关联的业务方)经过订阅的方式,把时时变动的数据时时的经过Push或Pull的方式拉到其业务端,进行一些业务处理。而Otter就是跨IDC的数据同步,把数据能及时反映到不一样的AA站。
数据同步可能会有冲突,暂时是以那个站点数据为优先,好比说A机房的站点的数据是优先的,无论怎么样,它就覆盖到B的。
【4】对于缓存。
一、注意切分力度,根据业务选择切分力度。把缓存力度划分的越细,缓存命中率相对会越高。
二、确认缓存的有效生命周期。
【5】拆分策略
一、按字段拆分(最细力度)。如把表的Company字段拆掉,就按COMPANY_ID来拆。
二、按表来拆,把一张表拆到MySQL,那张表拆到MySQL集群,更相似于垂直拆分。
三、按Schema拆分,Schema拆分跟应用相关的。如把某一模块服务的数据放到某一机群,另外一模块服务的数据放到其余MySQL机群。但对外提供的总体服务是这些机群的总体组合,用Cobar来负责协调处理。
Cobar相似于MySQL Proxy,解析MySQL全部的协议,至关于能够把它当作MySQL Server来访问的。