由于一些原因需要了解twitter的EarlyBird系统,至于对我们有什么作用...看看bloomfilter-chains就清楚了一个很好的移植,各处搜集加上自己的理解,现在作为一个总结放到这里:
EarlyBird是Twitter的实时搜索引擎,它目前服务于Twitter的tweet的搜索。建立之初,Twitter的工程师就为它定下几大目标:
Earlybird还有一个特点,每个用户得到的搜索结果都是“个性化”的。结果排序会根据用户的本地关系图等特征进行调整。总的来看,earlybird需要处理如下3种数据(Twitter的工程师称之为信号,signal):
- 静态信号(Static Signals):在初次建立索引的时候被建入,例如:tweet的语言
- 共鸣信号(Resonance Signals):随着时间的推移,需要不断动态更新的信息,例如:tweet被转发的次数
- 搜索用户的信息:和用户相关的信息,在发起搜索时被用来进行个性化排序。例如,本地关系图等
注:
twitter对存档tweet使用lucene做全量索引。
tweet的实时索引(10秒之内索引)由EarlyBird完成。
- 图的上半部分是tweet的索引构建阶段,下半部分是检索阶段。Earlybird服务是整个系统的核心,它负责建立、检索并维护着倒排索引数据。
- 索引构建过程如下:
- 用户发布的新tweet会被发送到一个队列(Ingestion Pipeline)里面。在这里,tweet的文本被分词,并被加上静态信号。
- 按照hash分割,tweet被分发到各个Earlybird服务上。Earlybird将tweet实时地建立索引
- 同时,另外有个一个Updater服务,它推送共鸣信号到Earlybird服务,动态地更新索引。
- 查询过程如下:
- 用户搜索请求搜先到达Blender服务(搜索前端服务器),Blender解析请求,并将搜索用户的本地社交图谱(Local Social Graph)合并到搜索请求中,往下发送到Earlybird服务。
- Earlybird服务执行相关性计算并排序。并将排序好的tweet列表返回给Blender。
- Blender合并各个Earlybird返回的列表,并执行一些重排序(Reranking),然后返回给用户
下面,我们主要关注一下Earlybird的索引结构。其中最主要的2个部分: Term字典 和 倒排索引 。
1、Term对应的倒排索引数据长度 2、指向位置倒排索引数据末尾的指针
这里保存倒排索引长度的目的是为了在多Term的拉链归并的时候,能按照索引长度进行排序,使得长度小的先先被合并,减少不必要的索引扫描。
这里有2个小问题:
- Q: 保存倒排索引长度的目的?
- A: 在多Term的拉链归并的时候,能按照索引长度进行排序,使得长度小的先先被合并,减少不必要的索引扫描
- Q: 为什么保存的是倒排索引末尾的指针,而不是头部?
- A: 如初识Earlybird中提到,Earlybird有对发布时间做优化,即,新的tweet有较高权值,那么它理应被先遍历到。
-->倒排索引
为了实现高吞吐、低延时地并发索引更新和检索服务,Earlybird采取了将分离索引的读和写的策略:每个实例维护了多个索引分段(目前是12个1),每个分段保存相对较少量的tweet(目前是223~840万1)。新增加的tweet首先被放到同一个索引分段中。这样,在任意时间,只有一个分段是在发生写操作的(我们称之为“活动分段”),而其它分段处于只读状态(称之为“只读分段”)。当一个活动分段写满之后,它就会被转换成一个只读分段,转换过程中,一系列优化会被执行,以提高效率:一份新的索引数据会被创建,原数据不会发生改变。当新数据创建完毕之后,原数据会被优化过的新数据替换掉。 postinglist会以1000为阈值划分为“长”和“短”的两类。短的,posting保持原样(24-bit文档id加上8-bit的位置信息),但是posting会按照时间逆序排列。对于长的postinglist,引入基于块(block-based)的来源于PForDelta2和Simple93的压缩算法。postings数据被存放在256字节定长的block中。block的最开头4个字节是未压缩的,接下来的4个字节存储了block的头信息,剩下248字节(1984bits)用来存储编码过后的变长的posting数据。原始的posting数据被转换成{d-gap, position}的对。头信息中保存着,后面的变长数据中存储了多少个{d-gap, position}对。这个n的计算方法如下:
下面是具体的数据结构
1、对Query进行分词成term。对每个term,查询Term dict中对应的postlinglist的指针。
2、通过指针,最多遍历4个pool中的slice数据,获得整个postinglist。
3、通过针对用户的特色处理之后返给用户结果。
为了加快处理速度,处于活动状态的分段数据是不会被压缩的。