-
Notifications
You must be signed in to change notification settings - Fork 51
Lucene
l 目的:去掉单独的小集群
在旧版黄金策项目中,索引的创建是一个的高配置的hadoop小集群来完成。
直接通过调用solr的API,在本地文件系统中创建,因为索引体积较大,需要大硬盘。
修改后,索引可以通过mapreduce在hdfs中创建,去掉了小集群,改用公司统一的大集群。
l 原理
Linux本地文件系统支持随机写,但是hadoop的hdfs不支持随机写,阅读lucene源码发现,lucene仅有很小的一段代码需要用到随机写,其目的仅仅是更新一个计数的标记,稍微改造下即可。
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
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
l 目的:减少fdt文件的大小
l 原理:
fdt文件存储的是记录的详细内容。
在一淘的项目中,大部分的数据类型均为数值型,且都是较小的值,默认long类型占用64byte,但是如果大部分的值都很小,完全没必要占用那么多字节,可以采用变长的方式存储,如果是0~128,仅仅使用一个byte就够了。
更详细的原理:http://user.qzone.qq.com/165162897/blog/1346322738
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的大小),不需要从倒排表重新构建
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秒,那是快多了。
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
l 目的:应对将来越来越多的机器,线性增长的问题,以及减少单个merge server的压力
l 原理:
目前solr 使用的是单个merge server,
merge server的作用是合并很多小的solr shard的结果,如果shards数量特别多,那么merge server的内存和计算都会成为瓶颈,故多层次merge serve 已经是必须要做的
原理拓扑图片参考如下: http://user.qzone.qq.com/165162897/blog/1355157666
l 目的:用于对多个列进行gourp by,并可以按照其他一个或多个列求max,sum,min,count,以及在此基础上的排序
l 原理
一淘项目大规模使用,实现方案从黄金策到一淘,改变了很多次,相关资料整理
http://user.qzone.qq.com/165162897/blog/1353199318
http://user.qzone.qq.com/165162897/blog/1349619426
经过几次的改版,性能提升很多,照比黄金策的能快上个几倍到几十倍(看具体使用情况),而且也使用上了原先黄金策不敢使用的下载功能。
一淘目前并没有使用,但是已经实现,详细的原理请参考
http://user.qzone.qq.com/165162897/blog/1350638560(性能不佳已经放弃)
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
l 目的:减少跳跃表对内存的消耗
后由于二分法需要单索引超过亿级别的记录数才能体现效果,以及一淘大量的需求需要使用group by ,sort,用二分法不占优势,故这个方案代码最终进行了回滚
l 原理:
直接参考这个地址吧:
http://user.qzone.qq.com/165162897/blog/1322011943