原文:Job Flavors at LinkedIn: Part I
译者:杰微刊兼职翻译汪建
作者:Caleb Johnson
我们相信LinkedIn能通过某种方式提供关于工作机会的个性化视图,而其他网站无法提供这种个性化。在我们新版的Job详情页面,它能够显示用户有价值的信息,比如该公司他们可能认识的人,这可以让他们比其他的应聘者拥有优势,或者可以让某个比较特别的工作比其他工作更加突出显示。然而,我们面临的最大的问题是让会员们去关注Job详情页面,对于候选人某个工作可能相当适合,但如果他们都从来没有看到Job详情页面,他们将会错过一个非常好的机会。
我们需要做的事就是去激发求职者的兴趣并找到解决问题的答案。“对于这个人这份工作最有趣的一件事是什么?”最初,LinkedIn有个工作列表的单纯功能,比如搜索结果的列表清单或者推荐工作列表。除了职位或者公司名称,没有其他任何方式可以使某个工作更突出。我们想在较新的体验版本中展示工作的所有“风格”,这将使某个工作变得特别。例如,会员可以从以前工作或学校的同事中了解情况,或者某个工作代表在薪资上有一个很好的跃升,这些都是为了帮求职者缩小范围并且为他们找到最好工作。在这篇文章中,我们将讨论我们为会员们展示Job风格的基础设施。
需求
在我们开始设计该系统时,我们有三个需求:
1、低延迟:我们想在LinkedIn的很多地方展示工作风格,但他们都有严格的延迟要求,比如Feed和工作搜索。在于相关利益者交谈后,我们确定对于95%的访问我们可以比原来增加不超过50ms的延迟(即95%的调用都应该花费小于50ms)。
2、可扩展性:我们需要用某种方式去创建该系统从而保证它的可扩展性,不仅要支持超过450万会员乘以15万个工作的视图的数据大小,而且还要支持大量的工作风格数据。为了让我们能在任何地方展示我们的工作风格,我们要支持最少每秒5000次查询(QPS),并且在高峰期要承受10000 QPS。我们还需要预留足够的空间来应付增长,因为我们已经看到从去年以来所有的工作页面已经增加了75%。
3、功能可扩展:应该要能很容易添加新的风格或者删除旧的风格,我们希望这是未来求职者在LinkedIn上找工作的核心体验,并且对于新的开发者它要能很简单的进行维护。添加新的风格不要求必须要知道以前的其他风格的知识,关于跟踪、建模、排名等等的相关知识也不需要。
架构总览
job风格生态系统由两个主要部分组成:一个无状态的Rest.li(https://github.com/linkedin/rest.li)层和一组被Rest.li调用的数据存储访问层。通过使用Rest.li和D2(https://github.com/linkedin/rest.li/wiki/Dynamic-Discovery),我们可以无限扩展这个中间层并保证其具备容错和负载均衡,好吧,也许不是无限,但几乎能能满足所有实际需要。前端客户端利用工作列表、会员和一系列的工作风格向我们的中间层发起请求去核查。客户端要明确要求他们想要请求的风格,否则一旦添加一个新的风格,我们可能突然就开始发送回去,客户端就会不知道如何展示它。
接着,对于每个风格的请求,工作名单被发送到相应的“风格委托者”上去为该用户获取必要的风格元数据。每个委托者都实现了一个具有两个功能的简单接口,
1)返回处理的风格的相关信息;
2)给定一个请求,返回它的风格是否有效,并返回相关风格的任何额外的元数据。
这使得获取风格信息的实际实现是完全开放的,截至LinkedIn不同团队提出的关于风格的新思路,我们不希望约束使用的技术和信息系统。因此,这就迫使该系统要高度解耦,该委托者要能对其他委托者保持独立运行。每个委托者都知道自己的依赖,也不需要依赖其他委托者的具体实现细节。话虽这么说,但有些委托者仍然有共同的依赖,但这将能够很好地避免重复调用,我们可以对下游服务做一个批调用,然后将信息拆分返回给请求它的每个委托者。例如,一个风格可能需要会员当前的学校信息,但是其他委托者又需要当前公司的信息,这两者都可以通过调用档案服务而获取到。幸运的是,我们可以在请求下游服务时简单地嵌入parseq-batching,它能够智能地为我们合并重叠的请求。委托者不必为这个功能做任何额外事情。他们只管按正常使用客户端即可,他们能通过空闲的委托者们得到高效的批处理服务。
一旦获得所有委托者的依赖关系,委托者将访问数据库去获取它相关的工作风格。随着每个委托者的结束(为安全起见将存在问题的委托者都做超时处理),有效的工作风格数据被发动到排名和选择引擎。我们对一个给定的工作风格用两个启发式的得分和排名:会员亲和力和工作风格亲和力。会员亲和力是由会员针对每个风格做出的历史反应决定,会员过去感兴趣的风格比被他们已经忽略或丢弃的风格会有更高的排名。工作风格亲和力是只对于某个工作的风格的强度:一个公司从会员当前的公司雇用数十个人,例如,如果会员能在该公司上有认识的人脉也许会更容易激发他的兴趣。一旦每个元组(会员、工作、风格)被打分和排名后,最高排名的风格将被选择并在响应中返回。客户端和服务器端发射跟踪事件继续构建这些模型。当新的风格被添加,他们会自动地合并到这些数据生命周期中,并要求添加新的风格委托者的开发者不能更改。
具体实现细节
一旦框架构建完成,剩下的所有事情就是找个最佳方式去获取内部实现。首先我们看看绘图团队:这个团队负责管理LinkedIn的整个社交图谱访问的API。图谱实时更新并且能让客户端根据自己的需要进行很复杂的精确查询。然而,这是要付出代价的,它能满足我们的可扩展性和功能可扩展,但速度不能满足,这些计算密集型操作需要花费较多时间,特别是对于大的子图交集的图谱,他可能会消耗高达几百毫秒的时间。例如,检测每个曾经去美国亚利桑那州立大学的而且现在在IBM工作的人,它要求两个图谱的交集,在40万会员中仅仅只能查询到500人的结果集。
我们意识到的是,虽然实时方面是不错的,但对于大多数风格来说,我们并不真正需要它,因为人们不会每天都在变学校和公司。验证正确性比即时发现付出代价少得多。我们可以通过日常的Hadoop工作预先计算这些需要大量计算的视图并且保存起来用于查询。例如,在Voldemort(我们的分布式键值对数据存储系统)中,我们可以保存一个会员在某些公司的工作关联。我们可以通过快速的会员查询验证此信息是否过期。这种数量级的查询比动态图谱快多了,一般总共仅需几毫秒。一些视图(像只有少量申请者的工作)本身需要实时数据备份它们,对于这些擅长分析相关关系的视图,它们具有低延迟(即使毫秒)。
结果和下一步
目前我们正在使用这个系统在不同的地方来装饰job,像我们的job邮件、job搜索页面、job主页、赞助公司动态和Feed建议。在不久的将来,我们将把这个整合到其他广告产品、inMails的招聘人员板块等等。添加这个功能后,我们看到了令人难以置信的令人鼓舞的成果,Feed和邮件页面增加了15%的访问,工作应聘和会员之间的消息发送活跃度增加了5%,甚至来自赞助公司动态服务的收入都增长了。
目前,job风格平台支持四种风格:
* 某个公司从你的学校已经雇佣了多少人。
* 某个公司已经从你的公司雇佣了多少人。
* 在这家公司你有多少人脉。
* 该项工作目前是否只有少于10个申请人。
虽然我们确实有很多风格(包括顾客适合度风格和优质订阅会员风格),但未来我们首要的工作是给搜索和建议更深入地整合进更多的的job风格。目前我们正努力让求职者可以通过风格过滤功能来查找工作,并且充分使用“Netflix-style”来进行分类。我们计划让我们的系统能自动化的实时去检测异常落果并报警及风格展示和点击的频率。
致谢
非常感谢Kunal Cholera、Jiuling Wang和Kaushik Rangadurai,帮忙规划架构最初的设计,以及我们的Feed、Companies、Jobs、Messaging和Search的同事为LinkedIn带来前沿的伟大的功能。如果你对创建这种伟大的产品感兴趣,并且想要影响人们的日常生活,我们长久在寻求有才华的工程师和数据科学家。可以通过我们的职业页面来了解更多信息。
更多精彩文章:
网友评论