金沙数据-大话搜索引擎第一季之初遇搜索(一)
时间:2023-03-20 07:12:01 | 来源:电子商务
时间:2023-03-20 07:12:01 来源:电子商务
本季内容概览:大概会花费4篇左右的文章为大家讲解一个普适率80%左右的垂直搜索引擎,内容涵盖需求分析、架构设计、模块切分、各种填坑、效果评测 直至上线运行。
本篇知识点概览:搜索需求分析、架构设计、功能块切分
一、放水篇(如果时间少请直接跳过阅读 二、干货篇 特别声明:如果有时间建议放水篇也阅读一下,无水万物枯萎凋零 搜索亦然)
2009下半年由于长期的疯狂加班身体开始抱恙,到最后几乎成了药罐子 每月3000元的工资3500元的药, 拿现在来说当时也算是活雷锋了吧!尽管领导一再挽留甚至开出可以让在家修养半年再回来工作的条件,最后考虑来考虑去还是感觉命更重要一些,于是带着对这家带我打开程序世界和服务2年多的企业软件公司的满怀歉意选择了say goodbye。
在家休息了两个月,身体快恢复的差不多的时候也马上快年关了。 为了过年不做无业游民,于是开始四处投简历参加面试。大帝都之大往往一天跑下来只能面试两家公司,不过有一天效率奇高上午就跑了两家公司。回家正好路过第二天约的要面试的一家小公司,于是抱着试试看的心理给hr打了个电话能不能提前来面一下,结果hr和技术负责人沟通了一下很爽快的答应了。(这么好的hr想必今天已大富大贵了吧)
只有两道简单的算法题,记得一道是给一个字符串不用api自己写代码实现去掉指定的字符,另一道是给一个字符串不用api自己写代码实现去掉指定的字符串。基本就是自己实现java的replace方法。回去的当天晚上就给了offer。我好长一段时间以为自己面的不错得到了这个offer,后来才发现两道题目只答对了第一道,另外一道根本没考虑去除掉这种情况 AABCBC字符串中去掉ABC字符串,因为中间的ABC去掉后前后字符串连接起来又可能形成了ABC!后来更知道之所以能被录用不是因为我答的多好,而是前面的几个兄弟答的更差。如今回想起来仍然感谢前面几位不知名的兄弟高抬贵手,让我误打误撞的进入搜索这个行业。
这家小公司我们姑且称为A公司吧,其实进去后发现并没有我想象的那么小,公司整体也上百号人了,主打在线订餐,从03年发展到09年已经当仁不让的成为北方区在线订餐的龙头老大。(当时大批的团购网站还都没有兴起,这块几乎是一两家独大的状态),A公司的搜索当时是使用的第三方的银杏搜索,效率和效果都糟糕的很,很多公司特定的需要也没法实现,迫切的需要自己公司内部研发的搜索引擎做支撑。搜索团队也是刚刚搭建,leader即是面试我的杨总,另外还有地主、老曹加我一共四个人。杨总是从亚马逊刚挖来的搜索专家、另外两个兄弟也是从其他团队调过来的工作5年以上的技术骨干, 能加入这样的一个团队我在暗自庆幸的同时也不免也压力重重,一个团队就我一个菜鸟 并且之前压根没听说过搜索引擎这玩意!
有句话"读万卷书不如行万里路,行万里路不如阅人无数,阅人无数不如高手指路“,在职业发展上我个人一直认为自己很幸运,经历的几个公司都遇到一个相当不错的老大,一个好的老大不仅会在技术上让你少走很多弯路并且在思维和做事方式上会让你职业生涯终身受益。在A公司是我技术成长最快的一段时光,大方向和思维上有杨总亲自指导,程序和工程上两位经验丰富的老大哥经常手把手不厌其烦的指导。相反大部分入行做搜索的可能没我这么幸运,经常对搜索最基本的分词、倒排、相似度模型这些很核心的地方只会稀里糊涂的用,也许一两行核心代码就搞定的事情结果出了问题根本束手无策。社区里太多这样的问题,而我询问提问者的时候大部分属于一个人单枪匹马就踏进搜索来了(上面leader根本不懂),或者没时间(浮躁懒惰)细看最基本的知识点,这一道门槛没过去大部分人可能就对搜索失去信心,认为不太好玩而离开(除非项目必须用),如此种种深感惋惜。
二、干货篇 由于杨总本身就是搜索的专家,所以结合当时业务特点在技术选型上团队很快就敲定 solr、lucene体系作为引擎内核,记得当时版本solr是1.4,lucene是2.9。要做的事情就是将第三方的银杏搜索干掉替换成自己公司的搜索引擎并同时实现一些当时无法支持的功能比如多维切面搜索,竞价搜索 同时也要对搜索排序效果有所改善。互联网的天气风云变幻莫测,由于A公司已经仙逝,具体需求我只能找一个demo给大家细讲。
上图基本上是当时搜索原始需求的一个原型,涵盖了大部分垂直搜索的常用功能点。
1.搜索结果数:表示搜索一个关键词后相关的餐厅数量,这个不仅仅用来展示也是后台计算分页的一个重要数据。
2.过滤筛选项:基本上就是餐厅服务和设施的一些筛选条件,有些是单选有些是多选。
3.维度切面搜索:这块是大家比较熟悉的,大部分电商网站都会有这个功能区,这个会让用户更快捷的通过几种维度筛选结果,里面有些还会包含复杂的树状下钻功能。这块在solr里面是facet做支撑的,当然前面的树状数据需要自己组织。
4.排序:搜索核心业务之一,一般默认就是相关度(当然这个大部分会加入业务因素和相关度一块排序),餐厅的会有评分,热销等等排序。
5.结果展示:这块主要展示搜索餐厅的具体信息,比如:名称、地址、评分、销量等等。
6.参与搜索的字段:这块是隐含的一个需求,在选择上也讲究颇多,如果选多了会召回好多不相关的结果导致排序结果很糟,选少了可能查全率又不够甚至出现东西本身就存在,而死活搜不出来的尴尬。 当时的选择是根据业务提的需求加上搜索数据统计分析(原来第三方的银杏搜索)确定了 餐厅标题,地址,地标,菜谱。
餐厅数量在60w左右的量级,每天搜索次数在100w左右,期待搜索性能在平均响应时间100ms以下(当时第三方搜索引擎的平均响应到了500ms)
。上图是当时的一个架构图,即便是现在来看对500w以下的数据量来说仍然不失为一个很不错的架构。当然看似简单的一张图,落地工作还是很繁杂的,下面我把主要模块功能列举一下以期给大家更方便的理解。
1.DB (餐厅信息的数据来源) 来自mysql和oracle(历史原因导致餐厅的不同信息是存在了不同类型的数据库中,这样在互联网行业中见怪不怪)数据总共大概来源于20个表,初做搜索的朋友们可能感觉奇怪为什么要用这么多表,其实在搜索引擎中只要用到过滤、排序、切面搜索、检索或者需要引擎返回的字段都需要采集到搜索引擎中。比如排序因素中的订单量、口味评分、评论数量这些尽管在界面上看不到 但是要用于排序公式中所以也要一并采集进来,而这些显然不会存在统一张表中,甚至有些数量需要程序做稍加计算才能得出。
2.dataCollector (数据采集系统) 负责将餐厅相关的变更数据近实时采集到searchDB中。技术细节采用了很简单的triger方式,将变更的信息triger到一个chang_list_in的表中,并给每条数据打上增删改的标记,datacollector的系统起来后会定期扫描此表并将最新的数据采集更新到searchDB中。
3. searchDB (搜索专用数据库) 此库中有两个核心的表,一个是根据datacollector采集到的数据形成一个宽表big_res_table,可以理解成此表中的字段和solr配置中的schema是一致的。 另外一个核心表是change_list_out,此表由big_res_table triger触发而来,记录了那些餐厅在big_res_table中进行了更新,并同时加上增删改的标记,以备下一个系统IndexBuilder使用。
4.indexBuilder(full/delta)索引创建系统。 此系统负责将变更的餐厅宽表信息big_res_table中的数据组织成solr的要求格式发给solr创建索引。系统可以以全量(full)方式启动或者以增量(delta)方式启动,全量方式启动则会将big_res_table中的数据全部往solr中发送一遍。增量方式启动则会以一个后进程方式监控change_list_out表的变化,近实时的去拉取变更的big_res_table数据发送给solr。(其实后来才知道这种是伪全量索引,不仅会引发一些数据问题,而且对索引和查询都没有起到全量的作用,后面的篇幅中我会逐一跟大家讲解如何调整架构去规避这些问题)
5. 引擎内核(solr主从服务) solr采用一主三从,读写分离的方式架构(可以类比mysql的主从),indexbuilder将数据发给solr master创建索引,三个solr slave会定期从solr master拉取最新的索引数据。这里解释说明一下, solr是一个独立的搜索应用服务器可以提供标准的http接口,solr本身是基于lucene的,而lucene本身只是一个搜索内核jar包(或者说lib库)要想做成一个搜索服务则还需要好多东西要做。如果把lucene比喻成毛坯房,则solr就可以看成是精装修并家电齐全可以拎包入住的公寓房,当然如果要过的更舒适的话则要再做些软硬装修(这个随着垂直搜索业务的逐渐复杂我们后面会讲到)
6.LB(负载均衡) load balance这个模块是用来做负载均衡,比如三个solr slave可能有一台机器配置好,则在流量分配上可以多分一些。另外有那个solr slave暂时不可用则 lb也负责将其下线, 并通知前面的search service模块不让请求再打过来。 (其实现在来看这部分完全可以用nginx替换掉,或者直接使用solr自己带的LB也可以)
7.search service(搜索服务) 搜索服务负责接受web的请求并将请求转化成solr可以理解的复杂语法(为了web层调用的方面searchservice封装了大量的solr语法和主业务解析,以http api的形式提供给web端),同时负责组织返回的数据(比如切面数据统计,树状结构),当然后期这里也处理了竞价和自然搜索的排序逻辑。
8.web (页面展示系统) 这块就是前面需求中的页面原型的动态数据实现,根据检索到的结果将数据展现出来,有些要求实时的数据则会从数据库获取其他地方再获取一遍和搜索的数据组合一块呈现给用户。
9.monitor(监控系统) 监控系统当时实现了两个主要工作,一个是发现任何solr服务不可用则自动发邮件通知搜索团队每个人,另一个则是将solr服务下线通知LB(当时是以文件交互方式)并同时周期性检测服务是否已经恢复,恢复的话则会自动通知LB上线并发邮件通知搜索团队每个人。
来到A公司之前,我一直感觉架构师就是写多了代码的猿或者根本就是个传说,进入搜索团队一个月才使我相信架构师真的存在,将一个复杂的系统瞬间给你庖丁解牛到一个个模块,并理清楚模各块之间的各种交互和业务逻辑,这并不是写上十年增删改查就能水到渠成做到的事情。好的架构师能使系统模块之间更松散的耦合在一块,并可以根据团队人数以及技术水平决定划分模块的粒度和多少,以使得整个团队人尽其才并且工作不强互相依赖,最后整个大系统就像堆积木般将每个模块轻松的组装在一起而不出差错。更好的架构师则其中的多个模块又可以被将来某个大型的系统重用!
好了,今天先和大家聊到这里,晚安。
---------------下篇预告---------------------
除了架构图中的模块还会有哪些你想不到的工程存在?
高大上的架构背后又有多少脏活累活?
一个词库的整理又会遇到什么逗比奇葩的事件?
分词和倒排在搜索引擎中到底承担了什么角色?
------------------------------------------------
以上疑问将在下篇中逐一揭密,敬请期待!
喜欢的朋友请扫描下方二维码关注公众号:金沙数据 您将会及时得到最新的文章。
http://weixin.qq.com/r/tDpqctPEN45IrZcR92_m (二维码自动识别)