架构师之路--搜索业务和技术介绍及容错机制

 今天和搜索部门一块儿作了一下MQ的迁移,顺便交流一下业务和技术。发现如今90后小伙都挺不错。我是指能力和探究心。我家男孩,不招女婿。html

  在前面的文章中也提到,咱们有媒资库(乐视视频音频自己内容)和全网做品库(外部视频音频内容),数据量级都在千万级。咱们UV,PV,CV,VV都是保密的。因此做为一个合格的员工来讲………………数值我也不知道。总之,这些数据做为最终数据源,要走一个跨多个部门的工做流才最终出如今用户点击搜索按钮出现的搜索框里。大致流程图以下:java

  这个流程图之因此没像以往同样手绘,嗯,那是由于:钢笔放在公司了。正则表达式

  这里面除了两个库都在咱们这边以外,其余的一个框是一个部门。咱们这边给pipeline的数据交付使用的是我开发的离线服务。pipeline将各个来源的数据作重复归并处理。就是一些视频内容是同样的,可是可能来源不一样或者名称有类似但可能不彻底相同,而其实是一个视频。打个比方,大学时看过一个电影叫<a Cinderella story>翻译成中文有的翻译成《灰姑娘的故事》也有翻译成《灰姑娘的玻璃手机》,可是能够根据其导演和演员表等判断实际上是同一个视频。这些相同的视频要聚合成一个专辑。推举最优质的描述做为专辑的描述。展开详情有各个来源的排序后视频列表。算法

  

  正常全网搜索也会将自家的视频放在前面:数据库

  这个归并处理你们可能也猜到了,并行计算嘛,用的是mapreduce。由于是视频数的组合操做,数量级是蛮大的。搜索引擎返回的是数据都是ID,真正的数据从详情部门返回。加个代理是啥意思?对调用端透明嘛,有修改只要改代理端。apache

  搜索引擎是独立的部门,没打过交道。可是我在上家公司的公司主要负责全公司的垂直搜索,数据来源都是关系型数据库,数据量不大,当时用的是搜索引擎用的是solr。分词器用的是开源的IK分词器。由于当时公司作的是面向企业家的高端人脉,搜索对人名,公司名等的检索结果的排序有不少特殊的要求,因此当时研究过度词器的源码,也对分词器进行了一些更加切合项目的改造。好比有个需求是过滤输入的html标签。可是在Solr中对索引读入后的第一个操做就是分词,使用Solr自带的或者外部的分词器。而后再对分好的词进行更细节的过滤或者近义词之类的。可是这第一步就直接破坏了文档的结构,变成了一个个单词,而不是html文档形式。再去除很麻烦并且效率低。因此我当时的作法是直接修改了IK分词器的源码,读入数据第一个操做先过滤标签。apache有现成的工具类。这样避免了读入读出带来的性能损耗。当时也作过测试,循环跑10w次用我改造后的分词器和不改造分词器用solr过滤器过滤正则表达式的方式比的话,执行效率大约高出20倍。当时的还发现不论是solr仍是ES,都是基于lucene的嘛,更适用于西文的一些检索。像中文检索不须要像西文那样须要语言处理器变小写而后再基于算法或匹配进行词根化。反而须要更多基于词典的,包括同义词,近义词这些。因此从分词这方面也是有不少的优化空间的。编程

  我的以为作搜索数据分析很重要。好比从日志分析中能够发现有些用户输入搜索关键词:贾跃亭,那么他颇有可能对包含“乐视”关键词的信息也颇有兴趣。发现了这个问题以后,我就对这类数据作了一个词库,进行了搜索和索引上一些词的双向绑定。就是至关于一个同义词的功能。建议将本文的题目放到几个搜索引擎里搜索一下,对比看看结果,挺有意思。缓存

   详情数据也是存在文档型数据库里,其实用mongoDB挺合适的。可是公司有统一的cbase集群,就直接放到cbase里了。我常常须要跟人家解释半天:cbase,couchbase,memcached都是啥关系。memcached你们都很熟悉。可是memcached不支持持久化。若是使用单纯的memcached集群,节点失效时没有任何的容错。应对措施须要交由用户处理。因此就产生了一个增强版的memcached集群:couchbase。数据层以memcached API对数据进行交互,系统在memcached程序中嵌入持久化引擎代码对数据进行缓存,复制,持久化等操做,异步队列的形式将数据同步到CouchDB中。因为它实现了数据自动在多个节点本分,单节点失效不影响业务。支持自动分片,很容易在线维护集群。cbase又是啥东西呢?这是我司对couchbase进行了一个二次开发,主要的改进点是对value的最大值进行了强行扩容:原本memcached最大Value设定是1M。咱们给扩容到4M。可是慎用大的value。value值从1K到不超过1M平均分布时,实际使用容量不超过50%时性能较好。若是大value不少,达不到这个值性能就会急剧降低。安全

 

  早在08年,09年的时候。facebook,mixi等国外知名互联网公司为了减小数据库访问次数,提升动态网页的访问速度,提升可扩展性,开始使用memcached。做为以facebook为标杆的人人网,这种技术也很快在其内部各个部门获得了普及。由于memcached集群采用的是服务器间互不通讯的分布式方式。客户端和服务器端的通讯采用的是分布式算法。这就是所说的节点失效时没有任何的容错。服务器

  这里提一个概念,就是常见的容错机制。我知道的,主要是6种。

  ☆ failover:失败自动切换

    当出现失败,重试其余服务器,一般用于读操做,重试会带来更长延迟。

    像咱们的MQ客户端配置,采用是failover为roundrobin。采用轮询调度算法来容错。

  ☆ failfast:快速失败

    只发起一次调用,失败当即报错,一般用于非幂等性的写操做。若是有机器正在重启,可能会出现调用失败。

    咱们的一个数据库虽然升级成了mariaDB。可是仍是一主多从。这时候写入主库失败采用的就是failfast方式。

  ☆ failsafe:失败安全

    出现异常时,直接忽略,一般用于写入日志等操做。

  ☆ failback:失败自动恢复

    后台记录失败请求,定时重发。一般用于消息通知操做。不可靠,重启丢失。

  ☆ forking:并行调用多个服务器

    只要一个成功即返回,一般用于实时性要求较高的读操做。须要浪费更多服务资源。

  ☆ broadcast

    广播调用,全部提供逐个调用,任意一台报错则报错。一般用于更新提供方本地状态,速度慢,任意一台报错则报错。

  

  读过《java并发编程实践》的朋友看到容错机制很容易会联想到java的fail-fast和fail-safe。周五和90后小伙子交流技术也正好聊到集合类的相关问题。有一个问题是在AbstractList的迭代器中,set操做作了expectedModCount = modCount。按理说不须要改变长度,为啥也要作这个操做。而实现它的子类set中都没有实现这个操做。个人想法是有一些实现set的方法有多是经过添加删除来变相实现的。总之,继续于这个AbstractList的实现类都会检查这个expectedModCount 和 modCount的一致性。不同会便可抛出并发修改异常,这就是failfast。而像CopyOnWriteArrayList这种的,写操做是在复制的集合上进行修改,不会抛出并发修改异常是failsafe的。

相关文章
相关标签/搜索