挑战邮箱搜索
做完 论坛搜索 和 音乐搜索 (续),接下来开始做邮箱搜索。
邮箱搜索与其它的搜索引擎最大的区别莫过于每个用户只能搜索自己的邮件内容。搜索引擎一般都是开放性的搜索,每个用户都有权访问所有的索引项目,每次搜索请求都会在所有的索引项目中进行匹配。而邮箱搜索是私密搜索,每个用户只能访问索引中很小的一部分数据,相应的,也就可以将每个用户的索引单独存放,以加快建索引和搜索的速度。
在最开始做方案的时候,因为种种原因,并没有选择给每个用户单独建一个索引的方案。毕竟,每个做方案的人在面临要建立上亿个目录的方案的时候,都会犹豫一下的。于是开始计算总的原始数据量,总的索引数据量,平均每个用户的原始数据量和索引数据量,每天的更新量,每天的搜索量等数据,以此来规划索引的布局和更新的策略。但在尝试了好几种布局方案之后,才发现无论如何布局,严重失衡的读写比例都会导致负载不均衡,更何况 lucene 的一些做法,会导致大量的额外数据读写,浪费本来已经很宝贵的IO。最后,只得退回到最初的想法上来。
定下来给每个用户单独建立一个 lucene 索引,接下来要做的事情当然就是如何安置这么多个 lucene 索引目录了。路径 Hash 是最容易想到的办法,而事实是,到现在为止我们也没有找到更好的途径。服务器是 Centos,文件系统是 Ext3,所以每个目录最多不能超过 1024 个子目录或者文件。单个目录下两级 Hash 子目录,1024*1024 已经是百万了,如果 Hash 算法比较均匀,每个子目录下放置 100 个左右的用户,那么就可以存放 1 亿用户的索引,基本满足了预算的要求。
为了方便上线部署,我们抽象了一个 node 节点的概念:一个 node 由一个索引目录及Hash子目录作为存储,一个或多个建索引进程更新索引,一个搜索进程对外提供搜索服务,再加上一些 memcached, memcacheq,memcachedb,mysql 以及 monitor 等辅助进程组成的独立的节点。每台服务器上根据负载可以部署一个或多个这样的节点。机器出现故障后,如果恢复所需的时间较长,而存储并没有损坏的情况下,可以将存储直接接到备份的机器上,重启所有的进程后,继续提供服务。
这么多用户在同一台机器上,并发的搜索量还好说,因为邮箱用户并不都是搜索的重度用户,麻烦的是并发的更新。邮件的到达和一些必要的更新操作,底层收发系统通过一个 memcacheq 通知给搜索系统,建索引进程读取 mq 里的消息,到指定的地方获取邮件内容,调用 java mail 库进行解信,用 IK 进行分词(词库来自:新浪拼音输入法),然后更新索引。 为了支撑巨大的更新,我们在同一个 node 上启动了多个进程,每个进程又启动了多个线程进行并发的更新。为了避免可能的 lucene 锁争用,我们在打开 lucene 索引前,还使用 memecache 对路径进行加锁;为了提高更新效率,我们将同一个用户的多封邮件打包,提交给某一个线程进行处理。大部分的情况下,这种策略都运行的很好,但也有意外:如果更新索引的过程出现了某种可恢复的错误,本次更新涉及到的所有的消息都会回写到 memcacheq 队列里。而这些回写,很可能会打乱正常的用户到信次序(某个用户多个消息批量回写也有可能被正常的更新打乱),最终在队列里形成诸如 ABACBCACB 这样的交叉消息。一旦某个用户上一次的更新还未完成,下一个线程就必须等待,这样的交叉更新,会严重的拖慢整体的更新速度。最后,我们也只能将回写队列与正常更新队列分开,单独为回写队列起一个处理进程,work around 吧。
起初在 12k 转速的 SAS 盘上做搜索压力测试,随机抽取用户,单个 node 能够很轻松的跑到 200 并发。可是最终的线上机器,为了节约成本,使用的是 7.2k 转速的 SATA 盘,还做了 RAID5 ,IO 随机小文件读取的瓶颈太明显了,随机抽取用户,连 50 并发都跑不上去。于是继续想办法。。。
(未完待续)
建议继续学习:
- 搜狐闪电邮箱的 Nginx/Postfix 使用模式 (阅读:32506)
- 怎样用好Google进行搜索 (阅读:14631)
- 淘宝搜索:定向抓取网页技术漫谈 (阅读:8190)
- 简析搜索引擎中网络爬虫的搜索策略 (阅读:5966)
- 几种常见的基于Lucene的开源搜索解决方案对比 (阅读:4623)
- 用Sphinx快速搭建站内搜索功能 (阅读:4401)
- 基于用户行为分析的搜索引擎自动性能评价 (阅读:4326)
- 互联网网站的反爬虫策略浅析 (阅读:4119)
- 附近地点搜索初探 (阅读:4112)
- 百度搜索URL参数解析 (阅读:4036)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:tangfl 来源: 福林雨-博客
- 标签: 搜索 邮箱
- 发布时间:2010-09-25 09:42:51
- [66] Oracle MTS模式下 进程地址与会话信
- [65] Go Reflect 性能
- [64] 如何拿下简短的域名
- [59] 图书馆的世界纪录
- [59] 【社会化设计】自我(self)部分――欢迎区
- [58] android 开发入门
- [58] IOS安全–浅谈关于IOS加固的几种方法
- [52] 视觉调整-设计师 vs. 逻辑
- [47] 读书笔记-壹百度:百度十年千倍的29条法则
- [47] 界面设计速成