淘宝拥有国内最具商业价值海量数据,如何挖掘出其真正的商业价值是数据平台的使命。数据产品最大特点是数据的非实时写入,在一定时间段内,整个系统的数据是只读的。为设计奠定了基础。
按照数据的流向来划分,我们把淘宝数据产品的技术架构分为五层,分别是数据源、计算层、存储层、查询层和产品层。位于架构顶端的是我们的数据来源层。数据源层产生的数据通过数据传输工具,准实时地传输到一个有1500个节点的集群上,对原始数据根据产品需求进行不同的MapReduce计算来得到中间状态结果。对于一些实效性要求高的数据,通过流式数据的实时计算平台(分布式系统),接收来自TimeTunnel的实时消息,在内存中做实时计算,并把计算结果在尽可能短的时间内刷新到NoSQL存储设备中,供前端产品调用。两者并不适合直接向产品提供实时的数据查询服务。因此针对前端产品设计了专门的存储层。在这一层,有基于MySQL的分布式关系型数据库集群MyFOX和基于HBase的NoSQL存储集群Prom。数据被我们近似均匀地分布到20个MySQL节点上,并对冷热数据分离,并根据需求使用不同的硬件配置。
由于全属性问题(属性值不同,比如布尔、枚举等),创建定制化的存储、现场计算并提供查询服务的引擎。选择了HBase作为Prom的底层存储引擎。以属性对(属性与属性值的组合)作为row-key进行存储,地让每个字段中的每一个元素都是定长的,这是为了支持通过偏移量快速地找到相应记录,避免复杂的查找算法和磁盘的大量随机读取请求。
使用中间层glider它负责各个异构“表”之间的数据JOIN和UNION等计算,并且隔离前端产品和后端存储,提供统一的数据查询服务。另一个功能是缓存管理。glider中存在两层缓存,分别是基于各个异构“表”(datasource)的二级缓存和整合之后基于独立请求的一级缓存。除此之外,各个异构“表”内部可能还存在自己的缓存机制。没有选择对汇总计算后的最终结果进行缓 存,而是针对每个分片进行缓存,其目的在于提高缓存的命中率,并且降低数据的冗余度。对于数据一致性,各异构“表” 除了返回各自的数据之外,还会返回各自的数据缓存过期时间(ttl),而glider最终输出的过期时间是各个异构“表”过期时间的最小值。这一过期时间 也一定是从底层存储层层传递,最终通过HTTP头返回给用户浏览器的。对于缓存穿透与失效(缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个存在的数据每次请求都要到存储层去查询,失去了缓存的意义。),如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。