Facebook是目前世界上最著名的社交网站,月活跃用户已超过10亿,每日登陆网站的用户超过6亿。如果从数据抽象的角度来看,Facebook的社交图不仅包括好友之间的关系,还包括人和实体以及实体之间的关系,每个用户,每个页面,每张图片,每个应用,每个地点以及每个评论都可以作为独立实体,用户喜欢某个页面则建立了用户和页面之间的关系,用户在某个地点签到则建立了用户和地点之间的关系……如果将每个实体看作图中的节点,实体之间的关系看作是图中的有向边,则Facebook的所有数据会构成超过千亿条边的巨量实体图(Entity Graph)。实体图中的关系有些是双向的,比如朋友关系,有些则是单向的,比如用户在某个地点签到。同时实体还具有自己的属性,比如某个用户毕业于斯坦福大学,出生于1988年等,这些都是用户实体的属性。图1是Facebook实体图的一个示意片段。
图1 Facebook实体图(Fbid是Facebook内部唯一ID编号)
对这个巨大实体图的搜索需求可以分为两类,一类是对于某类实体的搜索,常见的需求是根据实体名称搜索具体实体,实体图中的用户,图片,应用,地点等都可以成为被搜索的对象,比如搜索者搜索“Jordan”,搜索系统将所有名字里包含Jordan的其它用户搜索出来;另外一类搜索需求涉及到实体之间的关系,比如“Jordan都有哪些朋友”。
GraphSearch的定位就是成为能够让用户采用自然语言界面既能够搜索实体,也能够搜索实体关系的社交搜索引擎。这里需要强调的是:Graph Search不仅仅是传统的关键词搜索,还允许用户用自然语言来对结果进行搜索,即用户可以直接提问:”Facebook有哪些员工是华人”,而其可以通过自然语言处理技术理解用户真正想搜的内容,并给出精准的搜索结果。使用Graph Search,可以在这个巨量实体图上搜索类似以下复杂的自然语言查询:
a.Facebook的员工喜欢的餐馆有哪些;
b.毕业于斯坦福大学的人都喜欢看什么电影;
c.我的朋友喜欢去的旅游景点有哪些;
Facebook Graph Search是如何做到这一点的呢?为了理解其内部运行机制, 需要先了解Graph Search的倒排索引服务Unicorn系统。
Unicorn:Graph Search的基石
倒排索引是搜索引擎最重要的基础构件之一。对于通用的网页搜索引擎比如百度谷歌来说,倒排索引的功能是建立单词到出现过这个单词的网页列表之间的映射关系,这样,当用户输入某个查询词,搜索系统通过倒排索引找到出现过这个搜索词对应的网页列表,并按照若干排序因子对搜索结果排序,这样就完成了一次搜索过程。
Unicorn是建立在具有接近百亿节点的实体图上的倒排索引服务架构。与一般的网页搜索倒排索引不同,Unicorn具有几个独特的特性和挑战:
1. 不仅要对实体名称、评论内容等传统的文本内容进行索引,还需要对社交关系(朋友关系)用户行为(用户标记某个页面为liked)等建立索引。这里面临的技术挑战是:如何将社交关系这种涉及多实体关系的数据存入索引结构?
2. 为了能够快速响应用户查询,Unicorn会将几十亿节点以及千亿以上的边信息对应的索引结构保存在服务器内存中。传统的搜索引擎尽管也需要处理百亿级别的网页数据,但是索引结构往往是存储在磁盘中,通过外存索引加内存Cache的模式来加快查找速度。对于全内存的存储方式,如何设计整体架构来保存这种海量信息是非常有技术难度的。
3. 为了能够支持类似“Facebook的员工都喜欢什么餐馆”这种复杂查询,Unicorn定义了一套独具特色的集合操作符,通过操作符的嵌套与组合,不仅可以支持类似的复杂查询,还可以兼顾搜索的社交属性及搜索结果的多样性。
下面将从Unicorn的数据模型、整体架构及其定义的独具特色的集合操作符来讲解Facebook的技术人员是如何应对这些技术挑战的。
Unicorn的数据模型