关于搜索的缓存机制的入门,有一篇很好的文章,在这里简单总结一下,下面是文章的链接:http://www.tao-sou.com/840.html
对于一个正常的搜索流程,比如用户输入查询请求“夏季 连衣裙”,淘宝搜索引擎需要分别将存储在磁盘上的两个单词的倒排索引读入内存,之后进行解压缩,然后求两个单词对应倒排列表的交集,找到所有包含两个单词的文档集合,根据排序算法来对每个文档的相关性进行打分,按照相关度输出相关度最高的搜索结果。
以上这个流程涉及了磁盘读/写、内存运算等一系列操作,相对比较耗费时间和计算资源。如果将本次搜索结果存储在缓存中,下次遇到相同的查询请求,则可以直接将搜索结果返回,不需要经过上述的复杂流程进行计算。缓存一般用最快的内存设备进行存储,所以响应速度非常快,同时也省略了相当多的磁盘读取和计算步骤,有效地节省了计算资源。
淘宝缓存系统包含两个部分,即缓存存储区及缓存管理策略。缓存存储区是高速内存中的一种数据结构,可以存放某个查询对应的搜索结果,也可以存放搜索中间结果,比如一个查询单词的倒排列表。
最常见的缓存对象类型是用户查询请求所对应的搜索结果信息,比如宝贝的标题、宝贝URL等。图3给出了将搜索结果作为缓存内容的示例,缓存里保存了“连衣裙" ,“运动鞋”等用户查询,以及其对应的搜索结果。如果此时有另外一个用户输入“连衣裙”作为查询,则淘宝搜索引擎首先在缓存里面查找,发现己经存在这个用户查询项,则直接提取原先的搜索结果作为输出返回给用户。
另外一种比较常见的存储对象类型是查询词汇对应的倒排列表(Posting List)。图4是以单词倒排列表作为缓存内容的一个示例图,从图中可以看出,以搜索结果作为缓存内容的情况下,用户查询即使包含多个单词,也是作为一个整体存储在缓存槽里的;而以单词倒排列表作为缓存内容的方式,其存储粒度相对会小些,是以用户查询的分词结果存储在缓存槽里的。比如“夏季 连衣裙”这个用户查询,在搜索结果作为缓存内容情形下占用一项缓存槽,而在缓存倒排列表方式下会占用两个缓存槽,“夏季”和“连衣裙”各自占用一个存储位置。
这两种不同的缓存存储内容各自有其优缺点,对于搜索结果型缓存来说,其用户查询响应速度非常快,因为只需要进行查找运算即可返回结果,但是其粒度比较粗,比如在如图3所示的例子中,如果此时用户输入查询“连衣裙 韩版”,则淘宝搜索引擎会发现缓存里面并不存在这个查询,只能按照正常搜索流程,去调用索引数据并进行网页排序等运算。但是倒排列表型缓存因为粒度较小,会发现“连衣裙”这个查询词汇已经在缓存中了,此时只需要从存储在硬盘的倒排索引中读取“韩版”这个词汇的倒排列表数据,然后进行排序运算即可返回结果。由这个例子可以看出,倒排列表型缓存粒度小,所以命中率高,但是因为保存的只是倒排列表这种中间数据,所以仍然需要进行后续的计算才能返回最终结果,在用户响应效率方面慢于搜索结果型缓存。而搜索结果型缓存粒度大,如果在缓存内命中用户查询,则很快给出最终结果,但是命中率要低于倒排列表型缓存。
以上两种缓存对象是比较常见的缓存类型,还有一种不太经常使用的方式,即保留两个经常搭配出现单词的倒排列表的交集,以这种中间结果形式作为缓存内容。因为用户查询有很大比例是由2个或者3个单词组成的,对于多词构成的用户查询,搜索引擎在从硬盘读出每个词汇的倒排列表后,需要进行文档队列的交集运算。而如果能够事先将这些交集运算的计算结果缓存起来,则可以避免后续的交集运算,提高搜索系统返回结果的速度。但是这种词汇组合的数据量非常大,都放置到内存中往往很困难,所以一般这种中间结果会存储在磁盘上。这种类型的缓存不能单独使用,但是可以作为多级缓存中的一个缓存级别存在,对其他类型的缓存起到补充作用。
根据上面两种缓存存储结构,我们也可以设计一种二级缓存。二级缓存结构由两级缓存串联构成,第1级缓存是搜索结果型缓存,第2级缓存是倒排列表型缓存。当系统接收到用户查询时,首先在一级缓存查找,如果找到相同查询请求,则返回搜索结果;如果在一级缓存没有找到完全相同的查询,则转向二级缓存查找构成查询的各个单词的倒排列表,如果某些单词的倒排列表没有在二级缓存中找到,则从磁盘读取对应的倒排列表,进入二级缓存;之后,对所有单词的倒排列表进行求交集运算并根据排序算法排序输出最相关的搜索结果,将相应的用户查询和搜索结果放入一级缓存进行存储,并返回最终结果给用户。采用两级缓存结构的出发点在于能够融合搜索结果型缓存的用户快速响应速度和倒排列表型缓存的命中率高这两个优点。
另外就是缓存的管理策略,一种是淘汰策略,另一种是更新策略。
淘汰动态策略的缓存数据完全来自于在线用户查询请求,这种缓存策略的基本思路是:对缓存项保留一个权重值,这个权重值根据查询命中情况动态调整,当缓存已满的情况出现时,优先淘汰权重值最低的那个缓存项,通过这种方式来腾出空间。比较常见的动态策略包括:LRU策略、LandLord策略及SLRU等改进策略。
目前很多搜索引擎使用简单的更新策略,即在搜索引擎比较繁忙的时候不考虑缓存更新问题,而等到搜索引擎请求很少的时候,比如午夜等时间段,将缓存内的内容批量进行更新,使缓存内容保持和索引内容的一致。这种简单策略适合索引更新不是非常频繁的应用场景,对于索引更新频繁的场景,需要相对复杂些的缓存更新策略。