1.6.1 顺理成章的MySQL时期
作为一款在线流量分析产品,对其功能的要求自然是分析流量了。早期的Yandex. Metrica以提供固定报表的形式帮助用户进行分析,例如分析访问者使用的设备、访问者来源的分布之类。其实这也是早期分析类产品的典型特征之一,分析维度和场景是固定的,新的分析需求往往需要IT人员参与。
从技术角度来看,当时还处于关系型数据库称霸的时期,所以Yandex在内部其他产品中使用了MySQL数据库作为统计信息系统的底层存储软件。Yandex.Metrica的第一版架构顺理成章延续了这套内部稳定成熟的MySQL方案,并将其作为它的数据存储和分析引擎的解决方案。
因为Yandex内部的这套MySQL方案使用了MyISAM表引擎,所以Yandex.Metrica也延续了表引擎的选择。这类分析场景更关注数据写入和查询的性能,不关心事务操作(MyISAM表引擎不支持事务特性)。相比InnoDB表引擎,MyISAM表引擎在分析场景中具有更好的性能。
业内有一个常识性的认知,按顺序存储的数据会拥有更高的查询性能。因为读取顺序文件会用更少的磁盘寻道和旋转延迟时间(这里主要指机械磁盘),同时顺序读取也能利用操作系统层面文件缓存的预读功能,所以数据库的查询性能与数据在物理磁盘上的存储顺序息息相关。然而这套MySQL方案无法做到顺序存储。
MyISAM表引擎使用B+树结构存储索引,而数据则使用另外单独的存储文件(InnoDB表引擎使用B+树同时存储索引和数据,数据直接挂载在叶子节点中)。如果只考虑单线程的写入场景,并且在写入过程中不涉及数据删除或者更新操作,那么数据会依次按照写入的顺序被写入文件并落至磁盘。然而现实的场景不可能如此简单。
流量的数据采集链路是这样的:网站端的应用程序首先通过Yandex提供的站点SDK实时采集数据并发送到远端的接收系统,再由接收系统将数据写入MySQL集群。整个过程都是实时进行的,并且数据接收系统是一个分布式系统,所以它们会并行、随机将数据写入MySQL集群。这最终导致了数据在磁盘中是完全随机存储的,并且会产生大量的磁盘碎片。
市面上一块典型的7200转SATA磁盘的IOPS(每秒能处理的请求数)仅为100左右,也就是说每秒只能执行100次随机读取。假设一次随机读取返回10行数据,那么查询100000行记录则需要至少100秒,这种响应时间显然是不可接受的。
RAID可以提高磁盘IOPS性能,但并不能解决根本问题。SSD随机读取性能很高,但是考虑到硬件成本和集群规模,不可能全部采取SSD存储。
随着时间的推移,MySQL中的数据越来越多(截至2011年,存储的数据超过5800亿行)。虽然Yandex又额外做了许多优化,成功地将90%的分析报告控制在26秒内返回,但是这套技术方案越来越显得力不从心。