Skip to content
muyannian edited this page Jul 15, 2013 · 5 revisions

一、      lucene修改:可以直接在hdfs中创建

l  目的:去掉单独的小集群

在旧版黄金策项目中,索引的创建是一个的高配置的hadoop小集群来完成。

直接通过调用solr的API,在本地文件系统中创建,因为索引体积较大,需要大硬盘。

修改后,索引可以通过mapreduce在hdfs中创建,去掉了小集群,改用公司统一的大集群。

l  原理

Linux本地文件系统支持随机写,但是hadoop的hdfs不支持随机写,阅读lucene源码发现,lucene仅有很小的一段代码需要用到随机写,其目的仅仅是更新一个计数的标记,稍微改造下即可。

二、      lucene修改:frq频率文件采用局部zip压缩(海狗2中因比较消耗cpu放弃使用)

l  目的:减少frq文件的体积
frq文件的体积过大,导致每天下载索引过程缓慢,通过zip压缩,体积减少到了原先1/8。

l  原理

frq文件一般与tis文件组合使用,来完成倒排表的功能。比如,性别是 “男生”的记录有1000条,在frq中会保存这1000条记录的文档id列表,而且文档之间采用与前面文档的差值进行存储,如果重复值特别高的字段,对应的记录数就会特别的多,采用差值存储后,就会存在大量的重复值,如果针对每个倒排term,对应的doc list,都进行局部的zip压缩,那么索引体积的减少是非常可观的。

更详细的原理阐述如下:http://user.qzone.qq.com/165162897/blog/1344059861

三、      lucene修改:addIndexesNoOptimize优化

l  目的:

1.         实现创建索引过程可并行,通过提升mapreduce过程中的并行速度,提升创建索引的速度。

2.         实现增量索引,改变之前每天都要对全部数据重建索引的缺点。

通过这一个步骤的改变,我们创建索引的速度从12小时(现在黄金策为13~17小时),缩短到2小时,在我们给一淘的项目中,每天创建索引的时间为20~40分钟。

l  原理:

lucene的addIndexesNoOptimize是用于将一个外部的索引合并到当前的索引中,lucene之前的做法实际上就是一个copy的过程,最后在调用optimize后会将这个copy过来的索引重新读取最终合并成一个最终的索引。在我们看来这个copy的过程完全没有必要,反正这个文件是临时的,那索性就不进行copy,仅仅弄个类似linux系统的软连接的方式连接过来就可以了。

其一、我们可以通过增加并行度,实现创建很多小索引,然后统一进行合并。

第二,我们就不需要每天都创建全量的索引了,新增的索引直接通过软连接的方式连接过去好了

更详细的原理阐述如下:http://user.qzone.qq.com/165162897/blog/1344500162

四、      lucene修改:fdt文件压缩

l  目的:减少fdt文件的大小

l  原理:

fdt文件存储的是记录的详细内容。

在一淘的项目中,大部分的数据类型均为数值型,且都是较小的值,默认long类型占用64byte,但是如果大部分的值都很小,完全没必要占用那么多字节,可以采用变长的方式存储,如果是0~128,仅仅使用一个byte就够了。

更详细的原理:http://user.qzone.qq.com/165162897/blog/1346322738

五、      solr修改:termNum to termText构建优化

l  目的:提升group by查询速度,防止反复的构建

l  原理:

termNum to termText 是solr为了压缩fieldValue cache而实现,在一些长文本的上能极大的减少fieldValue的内存使用量。原理就是简单的通过将field的值进行编号,比方说 如果某一列值是 aaaaaa,bbbbbb,cccccc  ,编号后,1就代表aaaaa,2代表bbbbbb,3代表ccccc  ,如果字符串比较长,这种编号就能节省很多内存

termNum to termText采用类似128跳跃表的方式存储,故对内存消耗比较小。

但只这种构建需要通过遍历倒排表来构建,构建完成后采用lru cache的方式进行存储,由于现实数据量与内存的限制,内存中只能存储12个field,一旦有field被淘汰,当下次重新使用的时候,需要重构构建,如果某一个field,有几亿个不同的值的话,可以想象构建速度是很慢的。

我们采取的做法是当某个field被淘汰的时候,将内存里构建的数据dump到本地硬盘,下次需要重新使用的时候,从硬盘直接读取(1000万数据大约几百kb的大小),不需要从倒排表重新构建

六、      solr修改:field value cache构建优化

l  目的:提升group by的查询速度,防止反复的构建

l  原理

fieldvalueCache 顾名思义,存储的就是某一个field的值

在一淘80%的查询都是使用group by,如果每个field的值都去fdt文件中去取的话,需要进行大量的seek,文件系统是无法忍受的,故当需要进行某些列的group by的时候,solr会通过倒排表构建一个field的每条记录的值,放在内存中供查询使用。

但是构建的速度是很慢的(视数据的重复情况1000万需要5秒到60秒),而且由于内存限制我们只能存储12个field,采用lru方式进行淘汰。而我们有400多个不同的field,所以淘汰的问题经常会出现,故当发生淘汰的时候,我们把内存的数据直接dump到硬盘上,下次构建的时候从硬盘直接读取(1000万数据,每个field大约为40m),时间消耗为1~2秒,比起5~60秒,那是快多了。

七、      solr修改:不分词的field可以不存储

l  目的:减少fdt文件的体积

l  原理

fdt里存储的是数据的原始信息,是lucene索引中最大的文件,如果数值型的field不存储,那么fdt文件的大小将会是成倍的减少。

原始信息不存储,那么就不能通过从fdt中得到明细数据,从前面的两点优化中我们知道,这个值其实我们是可以从倒排表逆旋后生成的field value cache得到,但是需要限制用户一次只能查询小于12个field的明细(12是根据内存情况设置的field value cache的大小),而且首次查询由于要构建fieldvaluecache,查询速度会比较慢。

 

一淘由于目前硬盘资源很富余(使用量不足4%),故这个方案未采用,但是黄金策项目是值得使用的。

详细的描述如下:http://user.qzone.qq.com/165162897/blog/1349430078

八、      solr修改:group by sort多层次merge server

l  目的:应对将来越来越多的机器,线性增长的问题,以及减少单个merge server的压力

l  原理:

目前solr 使用的是单个merge server,

merge server的作用是合并很多小的solr shard的结果,如果shards数量特别多,那么merge server的内存和计算都会成为瓶颈,故多层次merge serve 已经是必须要做的

原理拓扑图片参考如下: http://user.qzone.qq.com/165162897/blog/1355157666

九、      solr拓展:多列group by sort实现

l  目的:用于对多个列进行gourp by,并可以按照其他一个或多个列求max,sum,min,count,以及在此基础上的排序

l  原理

一淘项目大规模使用,实现方案从黄金策到一淘,改变了很多次,相关资料整理

http://user.qzone.qq.com/165162897/blog/1353199318

http://user.qzone.qq.com/165162897/blog/1349619426

经过几次的改版,性能提升很多,照比黄金策的能快上个几倍到几十倍(看具体使用情况),而且也使用上了原先黄金策不敢使用的下载功能。

十、      solr拓展:count distinct实现(海狗2中更换为采用近似计算)

一淘目前并没有使用,但是已经实现,详细的原理请参考

http://user.qzone.qq.com/165162897/blog/1350638560(性能不佳已经放弃)

请点击这里参考新的方案

十一、         solr拓展:select in查询支持

l  目的:实现类似sql,select xxx from table where x in (select x from table1)的功能

l  原理:

采用变通的方式实现,分两次查询,第一次查询将需要过滤的id,并发的导出并写到hdfs中,

第二次构建一个自定义的lucene query,进行过滤查询

经过测试 对百万以内的数据量的过滤表现良好

详细使用资料请参考:http://user.qzone.qq.com/165162897/blog/1354954700

十二、         lucene修改:倒排表的实现由128位跳跃表更改为二分查找法(因性能不佳,海狗2中放弃使用)

l  目的:减少跳跃表对内存的消耗
后由于二分法需要单索引超过亿级别的记录数才能体现效果,以及一淘大量的需求需要使用group by ,sort,用二分法不占优势,故这个方案代码最终进行了回滚

l  原理:

直接参考这个地址吧:
http://user.qzone.qq.com/165162897/blog/1322011943

http://user.qzone.qq.com/165162897/blog/1329290887