深入浅出jcr之十二 key-value存储系统

      在写文章方面,惰性心理无时无刻不折磨着我,文章的标题已经列在那里很长时间,可是我就是不愿意打开,不愿意把心中所想描绘出来。类似的情况可能也折磨着很多的其他同学。虽然jackrabbit是一个小众的框架,看的人和想看的人非常的少,但是其中确实包含了很多值得我们学习和研究的技术和实现,当然也有很多不足,需要我们去改进。所以我强迫自己继续写下去。

上一篇文章讲到高亮和及时搜索的问题,在文章的最后我也提出了一些问题,就是如果将高亮去掉,那么势必会带来一个问题,那就是小文本文件的存储问题,一般有大型网络经验的人都知道,小文本存储在磁盘上,读取性能是非常低的,原因就是当前的磁盘的构造决定的。

当前市面的磁盘由磁头和磁片组成,数据都通过磁头写到磁片上,而写在磁片上又是根据磁道来划分,如果我们的小文件是单独存储的,那么一个磁头会将它们写在不同的磁道上,下次在读取的时候,磁头就需要不停的寻道,找到它想读取到的文件。寻道有两个过程,第一个是找到正确的磁道,而第二个过程是找到磁道上正确的起始位置。尤其是第一过程,寻道过程在大并发的情况下,磁头需要不停的进行寻道的工作,这个寻道是非常的消耗时间的。
所以小文件存储讲究的合并,即将小文件合并成大文件。

同样,在jackrabbit中,由于二进制文档数据被提取之后,是放到索引文件的,所以带来的一个问题是索引文件的大小成倍增加,在索引同步的时候,代价明显增大,这一点ahuaxuan在前文中也有较为相信的描述。而现在,我们就是要解决这个问题,提取之后的文本数据究竟应该放在什么地方。

是单独放在目录里面吗?对目录进行分级,一般多个大文件,比如视频文件之类的都会采取这种做法。对于一个平均长度是100kb-200kb的文本数据来说,如果也采取目录分级的方法来存放的话,那势必会存在非常多的这种文件,一旦又涉及到集群,那么对于jackrabbit来说,这一定是一场噩梦。

最好的方法是能够将这些小文件存储到一个大文件中,而且可以通过nodeid直接取到这样的小文本。这个时候我们就自然而然的想到使用key-value数据存储系统。比如市面上有tc,bdb,等等,但是他们都是local的,还是做不了数据的共享,无法使用到集群的场景下,一个clustorNode的数据无法和其他clustorNode共享。

这个时候我们又自然而然的想到memcachedb, tt+tc, mina+bdb.通过在local的key-value存储系统上套一个socket服务,一个local的key-value存储系统变成了一个remote的key-value系统,任何人都可以调用它们的服务。即使是在集群的环境下,也没有问题了。

大的方向确定之后,就是做各种性能测试。第一个排除的是memcachedb,之前有人跟我讲它的性能不是很好,我还不相信,经过自己的一轮测试下来,发现,在100kb文本的情况下,50000次save操作,耗时超过了我吃饭的时间。调整参数之后再测,稍微快一点,但是还是太慢了,有空整理一下我的测试结果。

为了确保bdb没有这么差的性能,我开始测试java版本的bdb在100k文本下的性能,经过多次测试,在我这块7000转的磁盘上,每秒钟的写入速度可以达到23m/s,读取速度38m/s,每秒钟读取100kb文本可以到350requests/second,这证明bdb是没有问题的。

那么memcachedb不够快应该是其本身的问题(当然也不排除我的参数配置不准确,即使不准确,也不应该差这么多)。

于是,我自定义了一个简单二进制协议,用mina+bdb,实现java版本的memcachedb,同样的测试,结果为写入14m/s,读取17m/s,每秒平均请求数为150 requests/s.

显然,这里有很大的优化的余地。至少网络io上不应该成为瓶颈。而且可以大胆的预测,在真正的存储系统中,磁盘将会是主要性能瓶颈。支持多磁盘的key-value存储系统可以有效的提高系统的整体读写性能。

同样我也测试过tc+tt,50000次100kb的save,耗时1300秒,在大文本的情况下性能也不咋滴。而且它还不支持多磁盘。更正,上面的结果是受网络环境的限制。我的测试网络带宽一会4m,一会20m,晕倒,等会把测试代码放到tc+tt server上测试

同时也希望使用过memcachedb存储大文本的同学出来说说它的性能到底如何。
上一篇:数据库监控维度脚本chkhealth.sql


下一篇:AD检查与排错:深入浅出Active Directory系列(三)