zoukankan      html  css  js  c++  java
  • Tair LDB基于Prefixkey中期范围内查找性能优化项目总结

    “Tair LDB基于Prefixkey该范围内查找性能优化”该项目是仅一个月。这个月主要是熟悉项目、。以下从几个方面总结下个人在该项目上所做的工作及自己的个人所得所感。

     

    项目工作简单总结


    以下是对阶段性的成果进行总结。并附有每一个阶段的总结报告。

    1. 项目实施计划的确定

            无论什么类型的项目(大、小,难、易),在项目开展之前都应该有个可实施的计划,一方面可以确保项目的进度,还有一方面也能防止有些人三天打鱼两天晒网的心态。在导师的细心指导下,我们确定了以下的几个基本计划及其最迟完毕时间预计。

    (1)搭建測试环境,把现有的Tair LDB接口測试一下,重点是Get/Put/Del和相应的Prefix系列接口以及衍生出来的getrange接口(该接口就是我们须要优化的)。包含思考今后的性能对照測试该怎样进行和准备相应的測试工具。

    完毕时间:7.12之前

    (2)分析Get/Put/Del和相应Prefix系列接口的数据在leveldb中存储有什么不同。

    完毕时间:7.15之前

    (3)在这个过程中仔细理解leveldb存储原理。

    完毕时间:7.23之前

    (4)同一时候可以參考下rocksdb,其他系统和paper。

    完毕时间:7.28之前

    (5)1-4点完毕后,看看是否有可实施的方案出来。

    完毕时间:8.1之前

     

    2. 项目环境的搭建和基本接口測试

            在了解tair这个开源KV缓存系统的基本功能和基本架构后,首先须要做的就是把环境搭好。然后依据官方TAIR命令说明进行基本接口如put/get/delete/get_range/prefix系列的命令行測试,让自己对这个系统的使用和基本功能有个大概的掌握。第一次搭环境总是各种不顺。系统库版本号的冲突、依赖软件、环境变量的设置、成功安装却启动失败等等问题,导致搭个环境花了一整天的时间,可能是自己经验不足,好在终于搭建成功。并在第二天记录下了整个搭环境的过程及期间出现的有价值的错误解决方式,一方面为后面安装多台dataserver时作參考,还有一方面也希望能为tair新手提供一点小小的帮助,尽量将搭环境浪费的时间降至最低。

    淘宝分布式 key/value 存储引擎Tair安装部署过程及Javaclient測试一例

    在測试过程中,发现tairJavaclient及命令行測试中都没有加入get_range測试接口,好在tairC++client已经实现了该接口。仅仅是没有封装成命令供client调用。而我们的项目主要就是优化这个接口,对其进行測试不可缺少。因此在掌握命令封装方法的基础上为其加入了get_range接口的命令測试。此时已经对基本接口的实现有了初步的了解,这些接口在client和服务端都有实现,client负责用户的请求解析,并将请求封装成数据包发送给服务端进行处理,服务端就是各种存储引擎。如我们关心的leveldb引擎,其真正实现了用户的请求操作,并将结果反馈给client。

    tair中对get/get_range接口的理解及为get_range加入命令行測试接口

     

    3. tair性能对照測试方案

            关于性能对照測试,自己没有什么经验。一方面自己写过的性能相关的C++程序或项目都不那么复杂,使用Linux内置的C++性能測试工具如gprof就已足够。没用过其他什么复杂的框架。还有一方面tair是分布式系统。相对较复杂,调研适用于分布式系统的C++性能測试工具也比較少,就算找到了工具还要花时间学习、费力去适应工具的条件。因为我们的需求相对不是非常复杂,全然没有必要去使用复杂的工具。

    在导师的指导下。我们终于决定自己写一个简单的性能測试工具,可以借鉴rocksdb等存储引擎的基准測试程序思路,主要关心服务端的极限QPS和单个操作的响应时间rt这两个衡量指标。

    tairldb存储引擎性能測试方案

     

    4. leveldb中prefix系列接口的特点及理解leveldb的存储原理

            关于leveldb的存储思想及原理看了不少參考资料和文档,每天看一点并结合源代码分析。渐渐明确了为什么不选B+树存储数据而採用LSM的存储结构,知道了为什么要有skiplist这样优化链表的结构,还下载了相关的论文想要细细研究其详细的实现原理。这些是基础,在此之上还有leveldb的分层存储和分级存储。分层指的是leveldb的数据首先存在memtable中,Put的数据达到一定量后变成immutable memtable,最后存到sstable file中。而sst file又进行分级管理(level 0 ~ level n)。level 0的files中key可能互相有重叠,而其他级的key都不会重叠,每一个level上的数据都是排好序的。还有其他的知识点。比方版本号管理实现的比較巧妙,通过引用计数可以有效的保护并发更新。一開始不知道get_range接口的数据都来自prefix_put/prefix_incr这种接口,因此对prefix系列的接口没有投入非常多的关注,以为与其他接口的差别就是prefix系列接口方便用户一次性可以put和get有着共同prefix的全部数据。

    后来在导师的指导下才知道prefix接口的优势在于:因为tair是依据hash分区的,而prefix系列的接口是依据prefixkey去hash的,所以能确保拥有同样prefix的key在同一台server上。这样在查找时就快得多,在查询有着同样prefix的数据时就不用到每一个server上找一遍。

    Tair存储引擎之中的一个Leveldb中数据的存储思想

     

    5.  对rocksdb存储引擎及相关paper的调研

            因为我们的项目是对范围查找进行优化,并提议使用bloomfilter的方案。bloomfilter之前有过了解并使用过简单的样例,因为hash不支持范围查找,因此bloomfilter本身也是不支持范围查找的,因此项目一開始我就进行了大量的调研,看能不能採取某种策略或优化手段使得bloomfilter可以支持范围查找,以证明方案的可行性。最后找到了几篇相关的论文,提到让bloomfilter支持范围查找确是可行的。仅仅是须要修改数据结构或方法,比方有一篇论文提出了一种分段Bloomfilter+多阶段查询的方法使得支持范围查找,还有一篇论文提出了一种相似于Bloomfilter的基于Trie数据结构的bloomfilter改造版,存储空间与原bloomfilter相当且查询性能较高。这些论文中提出的方案尽管具有可行性。但毕竟是实验性质的且算法较复杂,不适用于全部类型的范围查找。

    比方leveldb中的get_range接口,当中的pkey參数即key的prefix没有利用到。

    后来对leveldb的“升级版”rocksdb(Facebook开源存储引擎)进行了大量调研。因为在其官网blog中提到说rocksdb利用prefix信息使得bloomfilter可以支持范围查找。为了研究其怎样实现范围查找。就深入研究了rocksdb的部分代码。发现其对key的prefix信息生成bloomfilter实现前缀过滤功能,且这里的prefix长度是由用户指定,但rocksdb本身并没有实现范围查找的接口。受到这种利用prefix进行bloomfilter过滤思想的启示,我们提出了自己的方案,即使用prefix bloomfilter进行范围查找的过滤。

    当然rocksdb优化的地方还有非常多。抱着学习的目的,我也简单总结了我研究rocksdb部分代码时所示优化措施。

    对LevelDB的“升级版”存储引擎RocksDB的调研成果

     

    6.  基本可实施方案的成型

            有了基本思想后,我们就要考虑在leveldb中怎样利用该思想形成一个可实施的方案,我首先依据自己对leveldb的理解做了一个初步的方案,不够简洁。且没有考虑tairclient一些数据的特点。后来在导师的指导和建议下一步步改进方案,终于形成一份简洁的可实施方案。有了方案后,方案的详细实现就非常重要了。比方须要修改源代码中的哪些模块、详细怎么修改等。当然原则是修改越少越好。尽量不影响原来系统中已有的数据结构。遵循开闭原则。

    依据方案我首先给出了方案实现的伪代码,因为经验不足还是有诸多欠缺的地方及没有深入考虑的地方,这些不足导师都帮我一点点指出来并给出了建议方案,不仅让我更加深入掌握了tair ldb的很多其他知识,也让自己深感在C++项目方面经验的不足。须要不断深入的学习。

    Tair LDB基于Prefixkey的范围查找性能优化项目提议方案

     

    个人总结

    这一个月来。与其说是在做项目,不如说是在不断地学习。

    (1)首先这是个C++项目,对于一个曾经专攻Java的我来说算是个挑战,Java项目大大小小做过不少,看Java代码非常轻松,自己也维护过大型Java项目。帮其写过凝视啥的。而C++项目仅仅做过一个。就是前不久完毕的研究生论文项目(本科的课程设计就不说了,太水),还是自己一个人独立完毕,没有不论什么指导。做出的东西相信也是不完好的。

    好在自己看过一些C++开源项目。如Google的RE2正則表達式库,当时还对Google的C++測试方案进行了一定的研究(从Google开源RE2库学习到的C++測试方案),这对如今看Google的leveldb库有了一定的帮助。看tair项目过程中学到了不少曾经未掌握的C++基础知识,比方在函数传对象參数时最好使用引用方式传递(加&)而非复制方式传递,因为引用方式传递时形參和实參指向同一块地址,就不须要创建暂时对象。避免了内存拷贝。节省内存空间。还有一些语言细节方面的,比方在使用vector时用emplace_back取代push_back避免冗余的copy and move,还使用了一些C++11的特性如使用继承控制关键词override来防止在类层次结构上的不一致等等。尽管都是一些语言细节,但对于C++菜鸟来说非常值得学习和掌握。

    (2)其次,这是一个分布式系统,本以为自己对这块没有太大问题,因为自己曾经用过一些Java的分布式通信框架如Corba、WebService、RMI等,主要的通信原理还是清楚的,只是自己仅仅限于了解原理却没有深入的去了解其详细是怎样实现的。

    一開始仅仅知道分布式系统有个client实现和server端实现,但两者详细怎样交互链接、採用什么通信手段还是不清楚。后来在导师的指导下知道了两者的交互接口文件。加上底层的通信代理机制RPC渐渐对分布式通信原理有了更深入的理解。当然分布式系统除了分布式通信机制外还包含server端的负载均衡、数据的分布特点等。眼下对这块知识还是稍有欠缺,仅仅知道tair中使用了config  Server和data Server两种角色,使用一致性hash算法实现负载均衡,对照表描写叙述bucket与其存储节点标示符(如IP地址)间的映射。但详细的实现还是不甚了解,导致对tair系统的总体性把握不太好。

    自己对这块的实现还是非常感兴趣的。仅仅是眼下苦于找工作的压力仅仅能将该模块的研究延后。

    (3)最后,自己对自己在该项目中的表现不太惬意。可能有双方面的原因:一是自己的技术能力还不够强,看C++代码看的比較慢,有时候想不通一个问题思考许久还不得果,还好导师耐心指导,一点即通。二是个人性格所致。自己一向比較贪玩,一到周末就想着各种happy。还有不注意身体得了点小病,这些都影响了项目的进度,自知感到惭愧。

    后面的时间更加紧凑,一方面克服惰性尽自己所能做好项目,一方面还要准备工作,我会合理的时间,做到这一点对我来说是非常有价值的C++开源项目。

    版权声明:本文博主原创文章。博客,未经同意不得转载。

  • 相关阅读:
    test
    【转载】ASP.NET MVC 3 —— Model远程验证
    【转载】富有客户端技术之——jQuery EasyUI
    【转载】基于ASP.NET Web Application的插件实现,附DEMO
    【转载】浅谈C#中的延迟加载(1)——善用委托
    【转载】Winform开发框架之权限管理系统
    【转载】基于我的Winform开发框架扩展而成的WCF开发框架
    [转载]10大优秀的移动Web应用程序开发框架推荐
    [转载]C#泛型列表List<T>基本用法总结
    [转载]推荐一个被大家忽视的微软的反跨站脚本库AntiXSS V3.1
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4883405.html
Copyright © 2011-2022 走看看