项目这周就截止了,这算是我第一个有导师指导的真正意义上的C++项目,项目基本完成,想要实现的功能也已经实现,并做了大量的性能测试。不过这对于业界来说,可能完成的还不够成熟,还有许多待改进的地方,还不能马上投入使用,还需要进行严格的考验,毕竟tair的应用场景太重要了,不容一丝疏忽。但于我个人而言,帮助还是挺大的,不仅是多了一次有价值的项目经验,更是学到了一些项目之外的东西,比如计划的重要性,惰性的控制,时间的分配管理(找工作与项目进度产生冲突)等。好了,不多说了,在这最后一篇总结报告里首先给出性能测试结果,然后简单总结整个项目。
项目源码:https://code.csdn.net/lanxuezaipiao/tair
------------------------------------------------
Date Now: Sun Sep 7 13:52:09 2014
Memory size: 4GB
CPU core: 8 * Intel(R) Xeon(R) CPU E5450 @ 3.00GHz
CPUCache: 6144 KB
------------------------------------------------
自己写了个适用于多线程的性能测试程序,主要统计单个操作的平均响应时间rt(单位为micros/op)和服务端的吞吐量throughout(单位为ops/sec)。
sbin/tairstress -s server:port
OR
sbin/tairstress -c configserver:port -g groupname
-s, --server data server,default port:5191
-c, --configserver default port: 5198
-g, --groupname group name
-p, --pkey_num prefix key num
-n, --skey_num_per_key skey num for every pkey
-w, --writes write data with prefix_put
-r, --reads read data with get_range
-d, --deletes delete data with prefix_remove
-t, --threads thread num
-i, --is_histogram show histogram
-h, --help print this message
-v, --verbose print debug info
-V, --version print version
下面解释几个比较重要的参数:
-p:是用prefix_put存储数据时prefix key的数量,我这里用的prefix key统一格式为:keyXXXXX_,为了简单,
其中XXXXX就以数字表示,比如-p参数为100,那么这100个prefix key用范围表示为[key00000_ ~ key00099_]。
-n:是每个prefix key下所有suffix key的数目,同样这里suffix key的格式同样为数字表示的XXXXX。
比如-n参数为1000,那么一个pkey下的所有keys就表示为[keyXXXXX_00000 ~ keyXXXXX_00999]。
-w:表示是否用prefix_put存数据,其中存储数量量由上面的-p和-n两个参数决定。
-r:表示是否用get_range读取某个范围内的数据,这里为了简单测试,start_key定为'0',end_key定为'z'。
另外,get_range中pkey的数目为上述-p参数代表数目的2倍,一半与prefix_put时pkey相同,表示可以查找到,
另外一半是数据库中不存在的pkey,表示查找不到。
-d:表示是否删除数据库中用prefix_put存储的数据,如果该参数为true表示直接删除掉数据库中所有的数据,
以方便存储不同量级的数据。
-t:表示线程的数目。
-i:表示是否显示每个操作所花时间的统计,比如统计有多少次操作落在某个时间范围内,占所有操作的百分比等。
说明:下面的实验结果可能因为缓存影响、测试方案不同、机器不同等有所差异,这里仅提供一个参考,只是为了说明get_range接口的优化效果是有的。
这里以单线程下的测试结果为例进行演示(多线程一样操作,只是自己指定-t参数)。
(1)数据存储量为:-p 100 -n 1000,即10万条key/value记录,其中value是随机生成的。
a. 存数据
$ sudo sbin/tairstress -c 10.10.7.144:51980 -g group_1 -p 100 -n 1000 -w 1 -r 0 -d 0
writing pkey[key00000_ ~ key00099_] and skey[00000 ~ 00999] for every pkey, value is random generated...
pputs : 125.998 micros/op 7936 ops/sec
: Wrote 100000 times
: Deleted 0 times
: 0 get_ranges and 0 found the key
: Got errors 0 times
b. 读数据
b1. 优化前(即没有使用prefix bloomfilter过滤机制)
$ sudo sbin/tairstress -c 10.10.7.144:51980 -g group_1 -p 100 -n 1000 -w 0 -r 1 -d 0
get_range : 16594.800 micros/op 60 ops/sec
: Wrote 0 times
: Deleted 0 times
: 200 get_ranges and 100000 found the key
: Got errors 0 times
b2. 优化后(即使用prefix bloomfilter过滤机制)
get_range : 2523.195 micros/op 396 ops/sec
: Wrote 0 times
: Deleted 0 times
: 200 get_ranges and 100000 found the key
: Got errors 0 times
c. 删除数据
$ sudo sbin/tairstress -c 10.10.7.144:51980 -g group_1 -p 100 -n 1000 -w 0 -r 0 -d 1
deleting pkey[key00000_ ~ key00099_] and skey[00000 ~ 00999] for every pkey
premoves : 117.021 micros/op 8545 ops/sec
: Wrote 0 times
: Deleted 100 times
: 0 get_ranges and 0 found the key
: Got errors 0 times
下面就不重复演示存数据和删除数据的过程了,直接给出在不同数据量级下get_range接口在优化前后的对比。
(2)数据存储量为:-p 500 -n 1000,即50万条key/value记录。
a. 优化前
get_range : 6754.802 micros/op 148 ops/sec
: Wrote 0 times
: Deleted 0 times
: 1000 get_ranges and 500000 found the key
: Got errors 0 times
b. 优化后
get_range : 2439.725 micros/op 409 ops/sec
: Wrote 0 times
: Deleted 0 times
: 1000 get_ranges and 500000 found the key
: Got errors 0 times
从上面2个简单的实验结果,至少可以验证以下几个结论:
(1)随着数据量越来越大,不管是优化前还是优化后get_range接口的throughout都在不断提高,这说明数据量越大,tair表现的越好。
(2)上述实验结果显示优化前后提升的倍数不同,这主要是因为pkey数量和skey数量不同导致的,这些数字其实并不能代表什么,理论上用get_range越找不到性能就越好,如果用真实数据进行测试可能比这个数字高(数据量越大越高)也可能比这个数字低,但至少可以说明优化是有效果的。
7月末已经有了一篇中期总结(Tair LDB基于Prefixkey的范围查找性能优化项目中期总结),7月份主要是调研、学习tair及tair ldb层的相关知识,最终提出了一个能解决需求的项目提案(Tair LDB基于Prefixkey的范围查找性能优化项目提议方案),这个时候还未进行具体的编码实践。然后,第二个月就是根据这个提案的步骤一步步完成整个项目的编码实现,这个过程相对而言更加艰难,因为tair系统对我来说太大了,我不敢百分之百确定自己的想法和每个步骤都完全正确、都能用代码实现并整合到tair系统中正确的地方。就是一开始写了个简单的几行程序想要正确编译和调试,对我这个之前没用过automake、autoconf的人来说都够呛,搞了好几天才彻底搞懂怎么正确的编译和调试,这个问题解决了过后,后面代码的编写和编译就轻松了许多,我还写了几个简单的脚步程序,能够自动编译和重启tair服务。
7月末写的这份提案对我来说非常重要,因为我后面所有的编码工作都是基于这份提案来的,都是按照提案1、2、3的步骤一步步来的,每完成一个步骤就进行一次小小的测试,保证代码实现的正确性。8月份我也相应写了4份报告,前面的3份分别对应提案中步骤1、步骤2和步骤3的解决思路和代码实现,最后一份报告是解决前面三个问题过后出现的新问题(导师指导的),这4份报告如下所示:
1. 如何获取key的prefix_size问题:Tair LDB基于Prefixkey的范围查找性能优化项目之如何提取key的prefix_size
2. 如何建立prefix bloomfilter:Tair LDB基于Prefixkey的范围查找性能优化项目之如何建立prefix bloomfilter
3. 如何在get_range过程中使用prefix bloomfilter进行prefix key过滤:Tair LDB基于Prefixkey的范围查找性能优化项目之如何使用prefix bloomfilter进行过滤
4. 解决由添加prefix bloomfilter而产生的两个新问题:Tair LDB基于Prefixkey的范围查找性能优化项目之后续问题解决记录
每个步骤的进行当中也遇到了不少困难,特别是后半个月又面临各种找工作的压力,总是感觉时间不够用,我既不能为了工作放弃项目的进度也不能为了赶项目的进度而不顾工作,因此时间的分配上面做了些功夫,合理给自己安排了份简单的计划表,按计划来,不至于让自己太焦虑。还好最终结果是好的,项目最终赶了出来,但可能还有些bug,因此后面我会继续维护它。