分享

因事制宜 各展所长

 guli3057 2014-12-15

    2010年,当全世界都被云和服务于云的新型数据库的卓越性能所吸引时,雅虎的研究小组决定对NoSQL进行研究。他们开发出了用于评估新工具性能和发现最佳使用案例的YCSB(雅虎云服务基准测试)架构。随后,雅虎在一篇名为《用YCSB测量云服务系统》的论文中公布了他们的研究成果。

    虽然雅虎研究小组的研究非常出色,但是与任何论文一样,它无法将所有的东西都概括进来。总结起来,该论文没有涉及的内容包括:该研究没有提供给其他测试机构自行分析所需要的全部信息;尽管雅虎对Cassandra、HBase、雅虎PNUTS和一个简单的分片式MySQL(即shardedMySQL)部署进行了分析,但是并没有包括一些我们常用的数据库;雅虎在研究中使用的是高性能硬件,但对于大多数企业而言,这些数据库在使用普通硬件时的性能表现才更具意义。

    对AltorosSystems公司的研发工程师而言,雅虎的研究给了我们很大的启发,我们决定在他们的研究基础上再做一些研究。根据不同系统负载下所测得的NoSQL数据库性能,我们撰写了这份独立于厂商的NoSQL数据库分析报告。

    研究特色

    我们所说的NoSQL为非关系型数据库。凭借在容量、弹性和扩展性方面的优势,它们能够存储海量数据,以及与云计算系统协同工作,这些特点让它们深受用户喜爱。NoSQL数据管理系统天生没有表结构,数据模型灵活没有直观的复杂性,并且拥有始终如一的一致性(符合BASE,而不是ACID)。它们拥有一套简洁的API和很高的吞吐量,能够应对海量数据。

    2012年,NoSQL数据库的产品数量达到了120余种。产品种类的多样化,使得用户难以针对特定案例选择一款最佳工具。数据库厂商通常在定制硬件和软件设置上展示解决方案的优势。为此,我们希望进行一次独立、公开的研究,以对雅虎同行们所做的研究进行补充。

    我们对以下四款NoSQL数据库解决方案进行了分析与评估。为了保证研究过程的透明,以及结果的可验证性,同时将硬件差异导致的评估错误降到最低,我们选择使用亚马逊的虚拟机。

    Cassandra:一种列族存储

    HBase:同样采用面向列的存储

    MongoDB:一种面向文档的数据库

    Riak:一种键值存储

    我们还以这四款NoSQL数据库为基准,测试了MySQL集群和分片式MySQL。一些测试结果被公布后,部分观察人士认为,MongoDB不应该与其他NoSQL数据库进行比较,因为MongoDB更多的是以直接与内存协作为目标。我们也非常清楚这一点。不过,这次研究的目的是为不同的NoSQL数据库确定最佳使用案例,因此我们忽略了这些数据库各自所具有的特点,选择在相同环境中对它们进行测评。


点击查看原图

    工具、库和研究方法

    为了确定测试基准,我们使用了YCSB(雅虎云服务基准测试工具)。该工具包括下列组件:

    一个带有工作负载生成器的架构

    一组工作负荷场景

    我们已经在特定类型的工作负载下测量了数据库的性能。工作负载由指派给两个主要选项的不同分布所明确:

    执行哪些操作

    读写哪些记录

    针对数据存储的操作将随机选择,主要为以下类型:

    插入:插入一个新记录。

    更新:通过替换字段值更新记录。

    读取:读取记录,无论是随机选取的字段还是所有字段。

    扫描:以随机选择的记录值为起点,按顺序扫描记录,所扫描的记录数量从1至100之间随机选择。

    每个工作负载都以一张含有100,000,000份记录的表为目标,每个记录为1,000字节,并包括10个字段。每个记录通过一个类似“user234123.”字符串的主键进行识别。每个字段被依次命名为field0、field1。每个字段的值为由ASCII编码组成的随机字符串,每个大小为100字节。

    数据库性能由数据库计算基本操作的速度所衡量。基本操作指由工作负载执行器所执行的操作,其职责是驱动多客户端线程。每个线程都通过一系列的数据库接口调用来加载数据(加载阶段),并执行工作负载(处理阶段)。由于线程可控制生成请求的速率,因此我们可以直接控制数据库的输入负载强度。此外,线程可以测量延时和操作的吞吐量,并将这些测量数据报告给统计模块(如图①所示)。

    不同工作负载下对系统性能的评估包括:

    工作负载A:大量更新

    工作负载B:大量读取

    工作负载C:只读

    工作负载D:读取最新的

    工作负载E:小范围扫描

    工作负载F:读取-修改-写入

    工作负载G:大量写入

    每个工作负载包括以下内容:

    1)操作记录(读取或写入)的数量

    2)列的数量/记录

    3)一个记录的总大小或每个列的大小

    4)用于加载系统的线程数量

    本项研究还详细说明了每类工作负载的配置设置。我们使用的是以下默认设置:

    1)100,000,000个操作记录

    2)记录的总大小等于1KB(1000B)

    3)10个字段/记录,每个字段100个字节

    4)多线程客户端(100个线程)

    测试环境

    为了提供可以验证的结果,基准测试在亚马逊EC2(弹性计算云)实例上进行。YCSB客户端被部署在亚马逊大实例(LargeInstance)之上:

    7.5GB内存

    4个EC2计算单元(两个虚拟核,每个核有两个EC2计算单元)

    850GB实例存储

    64位平台

    高I/O性能

    EBS优化(500Mbps)

    API名称:m1.large

    每个NoSQL数据库均被部署在亚马逊超大实例中相同地理区域内的一个4节点集群上:

    15GB内存

    8个EC2计算单元(四个虚拟核,每个核两个EC2计算单元)

    1690GB实例存储

    64位平台

    高I/O性能

    EBS优化(1000Mbps)

    API名称:m1.xlarge

    亚马逊经常因为较高的I/O等待时间和较慢的EBS(弹性块存储)性能饱受诟病。为了克服这些缺点,EBS磁盘安装在一个条带化处理的RAID0阵列中,这样一来,理想情况下,性能有望提升两倍。


点击查看原图

    测试结果

    在展开对NoSQL数据库的研究之时,我们希望获得一个公平的结果,以展示每个特定任务的最佳解决方案。这也是我们决定在不同类型负载下对每个数据库进行性能测试,以及让用户决定哪种产品更符合其需求的关键原因。

    我们在研究中首先测试了加载阶段,期间有1亿份记录被输入到这个4节点集群中。在这些记录中,每份记录包含10个字段,每个字段中包含有100个随机生成的字节。

    结果显示,HBase拥有最佳的写入速度(如图②所示)。通过启用预先创建区(pre-createdregions)和延迟日志刷新(deferredlogflush)功能,HBase的写入速度达到了40Kops/sec(每秒操作)。Cassandra在加载阶段同样有不错的性能表现,写入速度为15Kops/sec。Cassandra首先通过文件追加方式将数据保存在提交日志(CommitLog)内,然后再将这些数据写入Memtable的列族内存存储中。一旦Memtable被写满,数据将以SSTable格式存储在磁盘中。顺便提一下,在这种“仅内存”模式中,MySQL集群也能够拥有更好的性能。


点击查看原图

    工作负载A:大量更新模式。工作负载A为模拟数据库大量更新的场景,这和电子商务网站的后台数据库访问模式很相似。工作负载的设置如下:

    1)读取/更新比例:50/50

    2)Zipfian请求分布

    在更新过程中,HBase和Cassandra的响应延迟时间不超过2毫秒,远远低于整体平均响应延迟时间(如图③所示)。与Cassandra相比,HBase的响应时间更快。HBase客户端在配置时关闭了自动刷新。更新将汇聚在客户端缓冲区内,缓冲区满了之后才将延迟的写入操作异步更新到服务器端。为了加快服务器上的更新处理速度,延迟日志刷新将被启用。在刷新期间,WAL(Write-AheadLog)编辑将被保留在内存中。

    Cassandra先将更新内容写在提交日志内,然后内存中的Memtable将被更新。虽然Cassandra的速度较慢,但是与HBase的延迟日志刷新相比却更为安全。


点击查看原图

    工作负载A:读取。读取期间,列族压缩使得HBase和Cassandra拥有更快的数据访问速度。HBase采用了本地LZO(Lempel-Ziv-Oberhumer)配置,Cassandra采用了谷歌的Snappy压缩编码。尽管计算时间变长了,但是压缩减少了从磁盘中读取字节的数量(如图④所示)。

    工作负载B:大量读取模式。工作负载B由95%的读取和5%写入组成。内容标记可以作为与这个工作负载相匹配的示例任务;添加一个标签为一个更新,但是大多数操作为读取标签。“大量读取”工作负载的设置如下:

    1)读取/更新比例:95/5

    2)Zipfian请求分布


点击查看原图

    在读取中,分片式MySQL的性能最好(如图⑤所示)。在“内存映射文件”类型缓存的加速下,MongoDB的性能与分片式MySQL的性能十分接近。内存映射文件被用于MongoDB中的所有磁盘I/O。Cassandra的键与行缓存也能够快速访问被频繁请求的数据。由于0.8版本增加了堆外行缓存功能,因此Cassandra具有优秀的读取性能,同时使用的内存也更少。键缓存在列族基础上保留了键在内存中的位置,规范了针对存储行的SSTable的补偿。有了键缓存,我们将不再需要在SSTable索引文件中查找行的位置。换句话说,每个键缓存命中为我们节省了一次磁盘搜索,每个行缓存命中为我们节省了两次磁盘搜索。在HBase中,随机读取性能较慢。不过,Cassandra和HBase通过列族压缩能够提供更快的数据访问。


点击查看原图

    工作负载B:更新。得益于延迟日志刷新,HBase在大量写入情况下拥有非常高的吞吐量和极低的延时(如图⑥所示)。在延迟日志刷新打开后,编辑操作将首先提交给Memstore。随后,汇聚起来的编辑操作将被异步刷新至HLog中。客户端方面,HBase写入缓冲器所缓存的操作将在自动刷新(autoFlush)选项设置为“是”后开始写入,这样也可以大幅提升写入性能。为了确保安全,在预写式日志达到了内存HDFS副本特定数量后,HBase会确认每个写入操作。HBase内存提交的写入延时基本上等于数据在网络中传输的延时。由于首先使用最快的操作方式,即附加方式,将更新写在提交日志中,然后再写入Memtable列族内存存储中,因此Cassandra展示出了更大的写入吞吐量。

    工作负载C:只读。工作负载设置如下:

    1)读取/更新比例:100/0

    2)Zipfian请求分布


点击查看原图

    只读工作负载模拟的是数据缓存系统。数据被存储在系统外,而应用只能对这些数据进行读取。得益于平衡树索引(B-treeindex),分片式MySQL成为了这一竞争中的胜利者(如图⑦所示)。

    工作负载E:小范围扫描。工作负载设置如下:

    1)读取/更新/插入比例:95/0/5

    2)最新的请求分布

    3)最大扫描长度:100个记录

    4)扫描长度分布:统一


点击查看原图

    范围扫描方面,HBase性能优于Cassandra(如图⑧所示)。HBase扫描为一种由HRegionScanner执行的分层快速合并式操作。HRegionScanner能够合并从HStoreScanner(每个列族一个)那里获得的结果,而HStoreScanner能够合并从HStoreFileScanner(列族中每个文件一个)那里获得的结果。如果打开缓存,服务器仅提供指定记录的数量,而不是反馈至HRegionServer对每个记录进行处理。

    与0.6版本相比,首次引入的随机分片算法使得Cassandra的扫描性能得到了大幅提升。

    Cassandra的SSTable是一种经过排序的字符串数据表,它可以被描述为:一个键值字符串对文件,而该键值字符串对的排序则是根据以特定顺序写入的键与键值对进行的。为了在范围扫描过程中取得最大性能,我们必须使用一个保序分割器(order-preservingpartitioner)。在保序行的范围内进行扫描的速度非常快,几乎与在一个连接索引中移动光标一样。但是数据库无法在集群中均匀地分布单个键和对应的行,因此随机分割器被用于确保数据分布的平均。在Cassandra中,这是一个默认的分割策略。

    在MongoDB2.5中,由{"_id":{"$gte":startKey}}查询触发的表扫描显示的最大吞吐量为20ops/sec,延时约为1秒。

    MySQL集群的性能低于10ops/sec,延时为400毫秒。由于被分割在集群中的多个节点上,因此系统能够使用优化器将SQL指令传输至查询计划中。这一计划的执行被分割在多个节点中。针对范围扫描,平衡树索引以>、<或BETWEEN的表达方式用于列比较。

    分片式MySQL的基础为散布在连接器中的键,并且不支持在集群中进行真实范围扫描。尽管单个切片的性能为10ops/sec,但是整个切片设置的性能接近40ops/sec,延时为400毫秒。MyISAM缓存的是索引块,而不是数据块。由于需要从OS缓冲器高缓冲那里重新读取数据块,因此会产生负载。

    Riakbitcask存储引擎不支持范围扫描。但是可以利用eleveldb和与主键相关的特殊$key索引通过二级索引实现这一功能。Eleveldb的性能不佳,在输入了50,000,000份记录后,性能开始下降。

    工作负载G:大量写入模式。工作负载设置如下:

    1)插入/读取比例:90/10

    2)最新的请求分布


点击查看原图

    在包含大量写入操作的工作负载中,HBase的性能最好,其次是Cassandra。MySQL集群的NDB引擎也能够很好地管理密集的写入操作(如图⑨所示)。

    正如你所看到的那样,市场上的NoSQL数据库并不完美。每个数据库都有自己的优势和劣势,而这些优势与劣势是否重要,完全取决于你的参数设置与任务类型。例如,某个数据库拥有优秀的性能,但是一旦记录数量超过了某一限制,它们的速度就会大幅下降。这意味着,该解决方案适用于中等强度的数据负载和高速计算,而不适用于需要大量读写的任务。此外,数据库的性能还取决于你的硬件性能。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多