搭建网页滤重系统的工作总结

标签: 网页 系统 工作 | 发表时间:2014-05-22 00:00 | 作者:草依山
出处:http://jser.me

趁最近工作业务不多,写篇博客关于 【搭建一个基于 网页相似度滤重的系统服务】 的相关工作。当作整理学习,温故知新吧。

项目旧况

我接手时的线上代码主要有如下特点:

  1. 旧代码的滤重效果和预期的不一致,而旧代码的作者已经离职,所以旧代码等于一个无人可以解释的黑盒。 只知道有问题,但是出了问题没人知道如何解决。

  2. 性能低下得无法容忍,由于线上出现问题没人知道如何修复,解决的办法只有重启。重启有事需要对旧数据进行重跑,因为程序运行效率低下,重跑耗时巨大,但是又无可奈何。

  3. 严重依赖数据库,几乎到处是select和insert,搞得整份代码支离破碎。甚至连数据库的表都没有好好设计,该建索引的地方没有建索引,不该建索引的地方滥建索引,等等十分拙劣的工程设计。

按我的经验判断这样处处是坑的代码,与其重构,不如我直接重写,然后我就哐当哐当开始重写了。

系统框架

项目开发语言选用 C++,功能主要分为五个模块:

  • 算法
  • 存储
  • 索引
  • 服务
  • 测试

1. 去重的算法有不少,在本系统中同时支持两种算法, shingle算法和 simhash算法。前者是旧代码中本来就在使用的。 后者是本人调研出来的,google出品的,资料丰富,好评如潮。

对于 simhash和[shingle]算法的评测效果可以发现,总体效果差不多,不过对于内容篇幅较小的文章, simhash的算法效果明显优于 shingle算法。 而且 simhash算法速度远快于 shingle算法(至少3倍以上吧)。在此值得一提的是, simhash是针对中文处理的的 simhash,具体原理请见 SimhashBlog

2. 对于滤重系统来说,数据的存储和索引和cache系统非常类似,不停的有新数据进来,所以也要不停的删除过期的数据,才能保证内存使用量稳定在一个可控的量级上面。

所以数据的存储采用 vector包装而成的 容量固定循环队列作为核心数据结构,在此称为 BoundedQueue。 容量固定是因为滤重系统也是个有时效性的系统,我们需要将过时的信息删除掉,所以使用 queue是天经地义的事情。

不过在此需要注意的是,在 c++stl里面的 queue的底层实现是用 deque这种双向数组,已经很大程度上提高了 pushpop的效率。 但是毕竟在 queue里的 pushpop都会直接或者间接的导致内存的申请和释放。

而用 BoundedQueue底层就是一个固定大小的vector,每次push或者pop只是循环的移动head和tail指针,无需内存分配。所以在此,使用 BoundedQueue的好处就显而易见了。

后来得知其实在boost里面有这种循环队列的结构,在 circular_buffer.hpp里面,不过其实这玩意也就那么回事,很简单,自己写也不难。

3. 有比较就会有查找,有查找就要有索引。

当我们用算法把一大段一大段的文档计算成一个特征值时,这个特征值在内存中就代表了该文档。而滤重就需要对特征值进行对比,去掉那些 特征值相似的旧数据。所以我们需要对当前 BoundedQueue队列中的所有数据在 push进来的时候,进行索引的建立,然后当数据 pop出去的时候,进行索引的删除。

在本项目中,数据只需要约保留最新的100W条数据。而且特征值占用空间很小,所以直接使用c++里的 unordered_map作为索引的数据结构(不选用 map因为 unoredered_map的查找和插入效率远快于红黑树实现的 map)。

本项目索引的设计是参考了 Mysql数据库里 InnoDB索引的设计,在 InnoDB中,数据必须有个主索引 primary_key,其他普通索引都是指向这个主索引,所以数据位置统一在主索引里面存储即可。

4. 在云计算时代,软件基本上都转服务化了,也就是功能以服务接口的形式提供。我个人非常喜欢服务化,服务化可以让功能和模块变得更清晰,而且可以跨语言的调用, protobufthrift都是非常优秀的 rpc解决方案。

在本项目中,使用的是 thrift来搭建服务。但是也因此发现了 thrift的一些恨铁不成钢的地方,详情见博文 ThriftBlog

5. 测试主要是 单元测试性能测试。单元测试使用 google的单元测试框架 gtest。 不得不说我非常喜欢gtest来写单元测试。

稍微有点工程经验的人都明白单元测试的重要性。在工作的时候,当业务需求比较紧急的时候,我们开发也会尽量用最快的方法去开发,从而能迅速能上线。 但是上线不是一个项目完成的标志。正如有人说的, 如果一个项目上线的时候是完美的,那说明这个项目上线上得太晚了。 互联网项目讲究 持续集成快速迭代,而这一切的坚实基础就是较为完备的单元测试。

如果没有单元测试,重构时会发生的事情就是,你重构的时间用了一个月,但是重构产生的新bug需要你用半年时间来修复。

性能测试就更是必需品了,值得一提的是,重写之后性能提高至少 十倍

总结一下重写之后主要改进的几个点:

  • 模块职责清晰,代码规范,性能提升至少 10倍
  • 无需依赖数据库。还是那句话。 没有依赖,就没有伤害。
  • 丰富的单元测试才能保证项目可以持续集成,快速迭代。
  • 运行稳定,再也没有那些乱七八糟的未知bug了。

感想

1. 有人说 写代码write less不是重点,关键是read easy。 。 读书的时候我不能很好的理解这句话,觉得代码优化就是尽提高代码的复用,从来达到 write less 的目的。 在公司干活了才能深刻体会到,把一个系统服务写得 read easy 是一件更需要功底和经验的事。

记得当初给同事讲解整个项目架构的时候,同事听完说表扬说代码逻辑很清晰。 为了让代码 read easy,确实多花了我不少工作时间,但是看来是值得的。

2. 写程序时的 开源心态:我一直尽可能的把每个项目都当成开源项目来写(哪怕由于公司的原因无法开源)。

它的好处就是:当有些功能模块【既可以写的很丑陋难懂但是很快就能写完,又可以写的清晰易懂但是需要废点脑筋】的时候,你会变得尽可能选择后者。 因为开源的最大好处是会让作者对脏乱臭的代码有 羞耻感,比 codereview的效果甚至都好。

3. 幸亏当时果断重写旧项目,否则我到现在估计还在修旧代码的bug。。

相关 [网页 系统 工作] 推荐:

搭建网页滤重系统的工作总结

- - _不是我干的 _
趁最近工作业务不多,写篇博客关于 【搭建一个基于 网页相似度来 滤重的系统服务】 的相关工作. 我接手时的线上代码主要有如下特点:. 旧代码的滤重效果和预期的不一致,而旧代码的作者已经离职,所以旧代码等于一个无人可以解释的黑盒. 只知道有问题,但是出了问题没人知道如何解决. 性能低下得无法容忍,由于线上出现问题没人知道如何修复,解决的办法只有重启.

[转]工作流系统

- - 小鸥的博客
如果数据库系统( database systems)像受人尊敬的智者讲述的条理清晰的故事,那么 工作流( workflow)就像一群乳臭未干的小子在大谈各自的“哲理”. 之所以这样讲,我是想指出, 工作流系统 ( workflow management systems)还处于技术发展曲线( technology hype curve)上的初级阶段.

Google的系统工程师(SA)如何工作

- freefish - Tim[后端技术]
本文根据系统管理领域知名博客 Thomas A. Limoncelli 的 What is system administration like at Google 整理而成,添加了部分笔者观点. Google的系统工程师(System Administrator)如何工作. 由于Google的服务已经集群化,系统工程师并不大量接触硬件比如做安装服务器等事情.

工作职位推荐系统的算法与架构

- - IT瘾-bigdata
作者:Preetha Appan. Indeed.com 每个月有两亿不同的访客,有每天处理数亿次请求的推荐引擎. 在这篇文章里,我们将描述我们的推荐引擎是如何演化的,如何从最初的基于Apache Mahout建立的最简化可用行产品,到一个在线离线混合的成熟产品管道. 我们将探索这些变化对产品性能指标的影响,以及我们是如何通过使用算法、架构和模型格式的增量修改来解决这些挑战的.

猫王VS耶稣:网页排名系统告诉我们谁更重要

- - 译言最新精选
译者: Luiz 原文地址: newscientist.com. 笛卡尔:排在历史重要人物的第82位.        伊萨克·牛顿、耶稣、亚历山大大帝,我们应该把谁排在第一.        提出这样的问题一度会被人嘲笑. 我们可以理性地把他们拿出来做比较,就像比较Twitter是不是比Apple更值得投资一样.

揭秘Facebook 广告系统核心算法Pacing工作原理 (含案例)

- - 互联网的那点事
Pacing是Facebook广告系统中花费预算的节奏的一个算法,Google Adwords里面有一个功能是设定好预算和最高出价,Adwords就可以自动通过出价调节,让你在这个限定的预算下获取最多的点击,Pacing这个算法和Adwords的这个功能很类似,都是通过调节出价,让广告主获得最大的ROI.

工作十年,在腾讯沉淀的高可用系统架构设计经验

- - 掘金 架构
在系统的开发过程中,很多开发者都为了实现系统的高可用性而发愁. 本文从研发规范层面、应用服务层面、存储层面、产品层面、运维部署层面、异常应急层面这六大层面去剖析一个高可用系统的架构设计需要有哪些关键的设计和考虑. 希望腾讯的经验方法,能够给广大开发者提供参考. 内容较长,您可以收藏后持续阅读. 1 高可用系统的架构设计思想.

Facebook 因为推错了 BGP 路由的配置,相当于直接把自己的所有系统从互联网上断开了。没法快速恢复是因为平时通过互联网工作的员工也访问不到。更厉害的是门禁系统也在断开的系统之内,员工的门禁卡失效没法物理进入机房维护。。

- - 抽屉新热榜
Facebook 因为推错了 BGP 路由的配置,相当于直接把自己的所有系统从互联网上断开了. 没法快速恢复是因为平时通过互联网工作的员工也访问不到. 更厉害的是门禁系统也在断开的系统之内,员工的门禁卡失效没法物理进入机房维护. 想看更多劲爆内容,请下载抽屉新热榜客户端 :.

壳系统

- Vernsu - It Talks-魏武挥的blog
经常有人被我问到“你用什么浏览器”时的答案是:傲游啦360啦,但事实上,这些都不是真正的浏览器,从技术角度讲,充其量只是在IE浏览器上加一个壳罢了. 在国外,壳浏览器是以“皮肤”的形式存在,纯属为了美化浏览器而用. 但在中国,壳浏览器成了一门生意. 奇虎的主要收入来源并非来自那个由于一场商战而赫赫有名的安全卫士,而是来自于360浏览器(它有两个版本,分别以IE和Chrome为内核).

秒杀系统

- - 开源软件 - ITeye博客
秒杀系统架构分析与实战. (反馈非常好的文章,推荐). (1)查询商品;(2)创建订单;(3)扣减库存;(4)更新订单;(5)付款;(6)卖家发货. (1)低廉价格;(2)大幅推广;(3)瞬时售空;(4)一般是定时上架;(5)时间短、瞬时并发量高;. 假设某网站秒杀活动只推出一件商品,预计会吸引1万人参加活动,也就说最大并发请求数是10000,秒杀系统需要面对的技术挑战有:.