基于  lucene  的站内搜索 tangfulin <tangfulin@gmail.com>  www.imobile.com.cn
<ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul...
<ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul...
关于手机之家 (1/2)‏
关于手机之家 (2/2)‏ <ul><ul><li>手机之家是一个旨在提供全方位的手机相关服务的资讯类网站。在 7 年的 </li></ul></ul><ul><ul><li>时间里,手机之家从无到有,已经发展成为极具人气、最受关注的手机产 <...
<ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul...
<ul><li>产品大全搜索 </li></ul><ul><li>新闻  CMS  搜索 </li></ul><ul><li>论坛搜索(默认只搜索标题) </li></ul><ul><li>论坛帖子及回复搜索 </li></ul><ul><li...
手机之家的搜索 V1.0(2/3)‏ <ul><li>实现了多个业务模块需要的搜索功能 </li></ul><ul><ul><li>不同的搜索字段 </li></ul></ul><ul><ul><li>不同的排序方式 </li></ul></u...
手机之家的搜索 V1.0(3/3)‏ <ul><li>运行概况 </li></ul><ul><ul><li>Dev by chaoqian ( http://www.longker.org/ )‏ </li></ul></ul><ul><ul>...
<ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul...
<ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul...
需求背景 (1/3)‏ <ul><li>重建索引 </li></ul><ul><ul><li>索引字段变更 </li></ul></ul><ul><ul><li>分词算法变更 </li></ul></ul><ul><ul><li>搜索结果异常(...
需求背景 (2/3)‏ <ul><li>缩短更新周期(及时更新) </li></ul><ul><ul><li>Google  索引  imobile  更新周期为  30  分钟 </li></ul></ul><ul><ul><li>V1.0 ...
需求背景 (3/3)‏ <ul><li>搜索大索引( V1.5 ) </li></ul><ul><ul><li>3000+ 万条记录的一个库, xml  原始文件 14G </li></ul></ul><ul><ul><li>V1.0  索引文...
<ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul...
目标 <ul><li>及时更新( 3 分钟) </li></ul><ul><li>快速重建( < 2 小时) </li></ul><ul><li>可配置(拥抱需求变化) </li></ul><ul><li>可监控(运维友好) </li></ul...
<ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul...
进度 <ul><li>2009 年 4 月 1 号  search 2.0 init (节日快乐!) </li></ul><ul><li>4 月 12 号,修改版本号为  1.5 </li></ul><ul><li>6 月 1 号, searc...
<ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul...
设计 (1/8)‏ <ul><li>分离索引与存储,二次读取 </li></ul><ul><li>分离读与写 </li></ul><ul><li>分离  update  和  rebuild </li></ul><ul><li>拆分大库和小库 ...
设计 (2/8) 分离索引与存储,二次读取 <ul><li>索引里只存储  id  ,其他的字段只索引不存储。 </li></ul><ul><li>优点: </li></ul><ul><ul><li>保持索引的大小为一个可接受的范围 </li>...
设计 (3/8) 分离读与写 <ul><li>优点: </li></ul><ul><ul><li>降低编程复杂度 </li></ul></ul><ul><ul><li>保证搜索服务的可用性,和可扩展性(可以将索引文件分发到多台机器上,同时对外提...
设计 (4/8) 分离  update  和  rebuild <ul><li>Rebuild  的同时, update  正常更新 </li></ul><ul><li>Rebuild  需要将重建这段时间的更新计入新的索引中 </li></u...
设计 (5/8) 拆分大库和小库 <ul><li>保证及时更新的同时,减少索引频繁同步(由写索引同步到读索引)带来的  io  压力 </li></ul><ul><li>更新频率 </li></ul><ul><ul><li>小库(最近更新库) ...
设计 (6/8) 拆分大库和小库(续) <ul><li>增加新记录: </li></ul><ul><ul><li>增加到小库 </li></ul></ul><ul><li>更新记录: </li></ul><ul><ul><li>从大库中删除(标...
设计 (7/8) 搜索端索引更新 <ul><li>小库每次同步到一个新的文件夹中 </li></ul><ul><li>保留最近打开的  n (2) 份小库索引目录 </li></ul><ul><li>检测到新的索引到达,关闭一个最旧的,打开新的...
设计 (8/8) 新索引预热 <ul><li>目的:消除新打开的索引上前几次搜索慢的问题 </li></ul><ul><li>实现: </li></ul><ul><ul><li>遍历一遍新打开的索引,将数据都读入内存 </li></ul></u...
<ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul...
实现 (1/8) 架构示意图 端口 1985 IndexRebuilder IndexUpdater Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 ...
实现 (1/8) 架构示意图 端口 1985 IndexRebuilder IndexUpdater Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 ...
实现 (2/8) IndexReceiver <ul><li>By Java , Daemon  程序 </li></ul><ul><li>监听端口,使用  SCGI  通讯协议 </li></ul><ul><li>使用  Monkey  为底...
实现 (1/8) 架构示意图 端口 1985 IndexRebuilder IndexUpdater Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 ...
实现 (3/8) IndexUpdater <ul><li>By Java , Daemon  程序 </li></ul><ul><li>多个索引共用,每个索引起一个线程 </li></ul><ul><li>可根据需要随时停止或启动单个索引更新...
实现 (1/8) 架构示意图 端口 1985 IndexRebuilder Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端...
实现 (4/8) IndexRebuilder <ul><li>By Java , Daemon  程序 </li></ul><ul><li>多个索引共用,每个索引一个线程 </li></ul><ul><li>重建索引时序图: </li></u...
实现 (5/8) IndexRebuilder <ul><li>切换索引过程 </li></ul><ul><ul><li>Updater  删除自己当前的索引和未更新完的 xml 文件 </li></ul></ul><ul><ul><li>Up...
实现 (1/8) 架构示意图 端口 1985 Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 Rebuild ...
实现 (6/8) Transfer <ul><li>Bash  脚本,每个 indexId  一个进程,由  ControlCenter  或  monitor  启动和停止 </li></ul><ul><li>监控索引快照目录 </li></...
实现 (1/8) 架构示意图 端口 1985 Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 Rebuild ...
实现 (7/8) Searcher <ul><li>By Java , Daemon  程序 </li></ul><ul><li>使用  Monkey  为底层 NIO  处理框架 </li></ul><ul><li>使用  SCGI  通讯协...
实现 (8/8)Utils <ul><li>Cleaner </li></ul><ul><ul><li>Bash  脚本,每个 indexId  一个进程 </li></ul></ul><ul><ul><li>用来删除 Searcher  已经...
<ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul...
性能测试结果 <ul><li>ab </li></ul><ul><ul><li>-n 1000 -c 10  ( 99%  545ms  100%  32838ms ) </li></ul></ul><ul><ul><li>-n 2000 -c...
<ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul...
部署上线 <ul><li>运行概况 </li></ul><ul><ul><li>updater , rebuilder  部署在  Imobile-SV25-B50  上 </li></ul></ul><ul><ul><ul><li>Intel...
线上运行观察 <ul><li>Slow search  比例: >1s 1.x%; >2s 0.2% </li></ul><ul><li>机器负载 : 49(search): 1~3; 50(update): <1 </li></ul><ul>...
<ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul...
开发中的一些收获 (1/5)‏ <ul><li>FileChannel.transferTo  拷贝文件失败: </li></ul><ul><ul><li>Fewer than the requested number of bytes are...
开发中的一些收获 (2/5)‏ <ul><li>Kill  的问题 </li></ul><ul><ul><li>Never kill smart frog, don't kill -9 </li></ul></ul><ul><ul><li>Ja...
开发中的一些收获 (3/5)‏ <ul><li>更新太频繁导致的磁盘  IO  问题 </li></ul><ul><ul><li>同一台机器目录之间同步:没有问题 </li></ul></ul><ul><ul><li>一拖二,一拖三 </li>...
开发中的一些收获 (4/5)‏ <ul><li>GC  引起的服务暂停 </li></ul><ul><ul><li>多个索引共用 Search 进程 </li></ul></ul><ul><ul><li>每个索引维持了多个  searcher ...
开发中的一些收获 (5/5)‏ <ul><li>Java server  程序的  trouble shooting </li></ul><ul><ul><li>性能问题: jprofile </li></ul></ul><ul><ul><li...
<ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul...
持续改进 <ul><li>配置文件改动检测,自动重新加载 </li></ul><ul><li>更智能的处理索引字段变更 </li></ul><ul><li>分词算法改进 </li></ul><ul><li>搜索关键字数据挖掘(搜索新词自动发现)...
Lucene 3.0 <ul><li>Lucene 2.9 </li></ul><ul><ul><li>Searchable.search(Weight, Filter, Collector): collector  终于可用了 </li></...
定制功能 <ul><li>在某些情况下作为数据库的替代数据源 </li></ul><ul><ul><li>类似淘宝搜索,按多个字段筛选,过滤,排序 </li></ul></ul><ul><ul><li>当前解决方案:使用  sql  从数据库中...
参考资料 <ul><li>Lucene </li></ul><ul><ul><li>http://lucene.apache.org/ </li></ul></ul><ul><ul><li>http://lucene.apache.org/ja...
<ul><li>更多讨论 </li></ul><ul><li>关于  imobile </li></ul><ul><ul><li>网站首页  http://www.imobile.com.cn/ </li></ul></ul><ul><ul><...
Upcoming SlideShare
Loading in …5
×

基于 lucene 的站内搜索

3,318 views

Published on

imobile 基于 lucene 的站内搜索, tangfulin 在 betasalon 上的分享

Published in: Technology
0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
3,318
On SlideShare
0
From Embeds
0
Number of Embeds
16
Actions
Shares
0
Downloads
151
Comments
0
Likes
9
Embeds 0
No embeds

No notes for slide
  • 手机之家是一个旨在提供全方位的手机相关服务的资讯类网站。在 7 年的 时间里,手机之家从无到有,已经发展成为极具人气、最受关注的手机产 品资讯网站。
  • 基于 lucene 的站内搜索

    1. 1. 基于 lucene 的站内搜索 tangfulin <tangfulin@gmail.com> www.imobile.com.cn
    2. 2. <ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul><ul><ul><li>目标 </li></ul></ul><ul><ul><li>进度 </li></ul></ul><ul><ul><li>设计 </li></ul></ul><ul><ul><li>实现 </li></ul></ul><ul><ul><li>测试 </li></ul></ul><ul><ul><li>上线,运维 </li></ul></ul><ul><ul><li>经验分享 </li></ul></ul><ul><li>将来:手机之家搜索 V2.0 </li></ul>目录
    3. 3. <ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul><ul><ul><li>目标 </li></ul></ul><ul><ul><li>进度 </li></ul></ul><ul><ul><li>设计 </li></ul></ul><ul><ul><li>实现 </li></ul></ul><ul><ul><li>测试 </li></ul></ul><ul><ul><li>上线,运维 </li></ul></ul><ul><ul><li>经验分享 </li></ul></ul><ul><li>将来:手机之家搜索 V2.0 </li></ul>目录
    4. 4. 关于手机之家 (1/2)‏
    5. 5. 关于手机之家 (2/2)‏ <ul><ul><li>手机之家是一个旨在提供全方位的手机相关服务的资讯类网站。在 7 年的 </li></ul></ul><ul><ul><li>时间里,手机之家从无到有,已经发展成为极具人气、最受关注的手机产 </li></ul></ul><ul><ul><li>品资讯网站。 </li></ul></ul><ul><ul><li>目前已有的一些统计数据: </li></ul></ul><ul><ul><li>a. 1000w+ 用户 </li></ul></ul><ul><ul><li>b. 3000w+ 帖子 </li></ul></ul><ul><ul><li>c. 1.1TB+ 附件 </li></ul></ul><ul><ul><li>d. 780w+ Page View/ 每天 </li></ul></ul><ul><ul><li>e. 5~10w 在线用户 /15 分钟 </li></ul></ul>
    6. 6. <ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul><ul><ul><li>目标 </li></ul></ul><ul><ul><li>进度 </li></ul></ul><ul><ul><li>设计 </li></ul></ul><ul><ul><li>实现 </li></ul></ul><ul><ul><li>测试 </li></ul></ul><ul><ul><li>上线,运维 </li></ul></ul><ul><ul><li>经验分享 </li></ul></ul><ul><li>将来:手机之家搜索 V2.0 </li></ul>目录
    7. 7. <ul><li>产品大全搜索 </li></ul><ul><li>新闻 CMS 搜索 </li></ul><ul><li>论坛搜索(默认只搜索标题) </li></ul><ul><li>论坛帖子及回复搜索 </li></ul><ul><li>手机铃声,主题,电子书,软件搜索 </li></ul><ul><li>二手交易搜索 </li></ul><ul><li>。。。 </li></ul>手机之家的搜索 V1.0(1/3)‏
    8. 8. 手机之家的搜索 V1.0(2/3)‏ <ul><li>实现了多个业务模块需要的搜索功能 </li></ul><ul><ul><li>不同的搜索字段 </li></ul></ul><ul><ul><li>不同的排序方式 </li></ul></ul><ul><ul><li>不同的更新频率 </li></ul></ul><ul><ul><li>Java 多进程,多线程实现 </li></ul></ul>
    9. 9. 手机之家的搜索 V1.0(3/3)‏ <ul><li>运行概况 </li></ul><ul><ul><li>Dev by chaoqian ( http://www.longker.org/ )‏ </li></ul></ul><ul><ul><li>最初基于 Lucene 2.2 ,当前 2.4.1 </li></ul></ul><ul><ul><li>07 年 12 月开始开发 </li></ul></ul><ul><ul><li>08 年 12 月随新版系统上线 </li></ul></ul><ul><ul><li>部署在 Imobile-SV39-A49 上: </li></ul></ul><ul><ul><ul><li>X86_64 , 8 cpu @ 2.50GHz , 32G mem </li></ul></ul></ul><ul><ul><ul><li>CentOS release 5.2, JDK64 1.6, </li></ul></ul></ul><ul><ul><li>搜索: 35+ 万查询 / 天,高峰期 > 20 次 /s </li></ul></ul><ul><ul><li>更新: 平均 15 条 / 分钟 </li></ul></ul>
    10. 10. <ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul><ul><ul><li>目标 </li></ul></ul><ul><ul><li>进度 </li></ul></ul><ul><ul><li>设计 </li></ul></ul><ul><ul><li>实现 </li></ul></ul><ul><ul><li>测试 </li></ul></ul><ul><ul><li>上线,运维 </li></ul></ul><ul><ul><li>经验分享 </li></ul></ul><ul><li>将来:手机之家搜索 V2.0 </li></ul>目录
    11. 11. <ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul><ul><ul><li>目标 </li></ul></ul><ul><ul><li>进度 </li></ul></ul><ul><ul><li>设计 </li></ul></ul><ul><ul><li>实现 </li></ul></ul><ul><ul><li>测试 </li></ul></ul><ul><ul><li>上线,运维 </li></ul></ul><ul><ul><li>经验分享 </li></ul></ul><ul><li>将来:手机之家搜索 V2.0 </li></ul>目录
    12. 12. 需求背景 (1/3)‏ <ul><li>重建索引 </li></ul><ul><ul><li>索引字段变更 </li></ul></ul><ul><ul><li>分词算法变更 </li></ul></ul><ul><ul><li>搜索结果异常(记录重复,记录丢失) </li></ul></ul><ul><ul><li>索引文件意外损坏 </li></ul></ul><ul><ul><li>V1.0 :手工重建,人工参与重建过程,重建过程中不能正常更新 </li></ul></ul><ul><ul><li>V1.5 :自动重建,重建过程中正常更新原来的索引 </li></ul></ul>
    13. 13. 需求背景 (2/3)‏ <ul><li>缩短更新周期(及时更新) </li></ul><ul><ul><li>Google 索引 imobile 更新周期为 30 分钟 </li></ul></ul><ul><ul><li>V1.0 索引更新周期为 15 分钟 </li></ul></ul><ul><ul><li>V1.5 预期更新周期为 3 分钟,实际为 1-5 分钟 </li></ul></ul>
    14. 14. 需求背景 (3/3)‏ <ul><li>搜索大索引( V1.5 ) </li></ul><ul><ul><li>3000+ 万条记录的一个库, xml 原始文件 14G </li></ul></ul><ul><ul><li>V1.0 索引文件为 13 G ,无法快速更新 </li></ul></ul><ul><ul><li>V1.5 索引文件为 3.9G (还是无法快速更新?) </li></ul></ul><ul><ul><li>V1.5 完整重建一次: 140 分钟 </li></ul></ul>
    15. 15. <ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul><ul><ul><li>目标 </li></ul></ul><ul><ul><li>进度 </li></ul></ul><ul><ul><li>设计 </li></ul></ul><ul><ul><li>实现 </li></ul></ul><ul><ul><li>测试 </li></ul></ul><ul><ul><li>上线,运维 </li></ul></ul><ul><ul><li>经验分享 </li></ul></ul><ul><li>将来:手机之家搜索 V2.0 </li></ul>目录
    16. 16. 目标 <ul><li>及时更新( 3 分钟) </li></ul><ul><li>快速重建( < 2 小时) </li></ul><ul><li>可配置(拥抱需求变化) </li></ul><ul><li>可监控(运维友好) </li></ul><ul><li>SLA : always 可写, always 可读,异常的时候唯一的表现是更新延迟 </li></ul><ul><li>高性能,能承受较大的流量,并发压力 </li></ul>
    17. 17. <ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul><ul><ul><li>目标 </li></ul></ul><ul><ul><li>进度 </li></ul></ul><ul><ul><li>设计 </li></ul></ul><ul><ul><li>实现 </li></ul></ul><ul><ul><li>测试 </li></ul></ul><ul><ul><li>上线,运维 </li></ul></ul><ul><ul><li>经验分享 </li></ul></ul><ul><li>将来:手机之家搜索 V2.0 </li></ul>目录
    18. 18. 进度 <ul><li>2009 年 4 月 1 号 search 2.0 init (节日快乐!) </li></ul><ul><li>4 月 12 号,修改版本号为 1.5 </li></ul><ul><li>6 月 1 号, search 1.5 在线上试运行 (节日快乐 again !) </li></ul>
    19. 19. <ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul><ul><ul><li>目标 </li></ul></ul><ul><ul><li>进度 </li></ul></ul><ul><ul><li>设计 </li></ul></ul><ul><ul><li>实现 </li></ul></ul><ul><ul><li>测试 </li></ul></ul><ul><ul><li>上线,运维 </li></ul></ul><ul><ul><li>经验分享 </li></ul></ul><ul><li>将来:手机之家搜索 V2.0 </li></ul>目录
    20. 20. 设计 (1/8)‏ <ul><li>分离索引与存储,二次读取 </li></ul><ul><li>分离读与写 </li></ul><ul><li>分离 update 和 rebuild </li></ul><ul><li>拆分大库和小库 </li></ul><ul><li>new open 小库(小库滚动), reopen 大库 </li></ul><ul><li>新索引预热 </li></ul><ul><li>更多: http://blog.fulin.org/category/tech/lucene </li></ul>
    21. 21. 设计 (2/8) 分离索引与存储,二次读取 <ul><li>索引里只存储 id ,其他的字段只索引不存储。 </li></ul><ul><li>优点: </li></ul><ul><ul><li>保持索引的大小为一个可接受的范围 </li></ul></ul><ul><ul><li>提高索引读取速度 </li></ul></ul><ul><ul><li>提高索引 cache 效率 </li></ul></ul><ul><li>缺点:搜索时需要额外的请求来获取其它必须的字段( lucene + db 方案) </li></ul><ul><li>衍生项目: blackdb , memcache 协议 + bdbJE 存储 </li></ul>
    22. 22. 设计 (3/8) 分离读与写 <ul><li>优点: </li></ul><ul><ul><li>降低编程复杂度 </li></ul></ul><ul><ul><li>保证搜索服务的可用性,和可扩展性(可以将索引文件分发到多台机器上,同时对外提供服务) </li></ul></ul><ul><ul><li>提升索引更新速度 </li></ul></ul><ul><li>缺点: </li></ul><ul><ul><li>需要移动索引文件 </li></ul></ul><ul><ul><li>需要额外的索引更新逻辑( reopen ) </li></ul></ul><ul><ul><li>无法使用当前设计中的 lucene 的 real-time search </li></ul></ul>
    23. 23. 设计 (4/8) 分离 update 和 rebuild <ul><li>Rebuild 的同时, update 正常更新 </li></ul><ul><li>Rebuild 需要将重建这段时间的更新计入新的索引中 </li></ul><ul><li>Rebuild 完成后,通知 update 切换到新索引上来,并继续更新 </li></ul><ul><li>进程间通信,当前使用最原始的基于文件的方式 </li></ul>
    24. 24. 设计 (5/8) 拆分大库和小库 <ul><li>保证及时更新的同时,减少索引频繁同步(由写索引同步到读索引)带来的 io 压力 </li></ul><ul><li>更新频率 </li></ul><ul><ul><li>小库(最近更新库) 1 分钟 </li></ul></ul><ul><ul><li>大库(历史库) 1 天到 1 周,可配置 </li></ul></ul><ul><li>并行搜索,加速搜索速度 </li></ul><ul><li>问题: group by </li></ul>
    25. 25. 设计 (6/8) 拆分大库和小库(续) <ul><li>增加新记录: </li></ul><ul><ul><li>增加到小库 </li></ul></ul><ul><li>更新记录: </li></ul><ul><ul><li>从大库中删除(标记删除) </li></ul></ul><ul><ul><li>从小库中删除(物理删除) </li></ul></ul><ul><ul><li>增加到小库 </li></ul></ul><ul><li>删除记录 </li></ul><ul><ul><li>从大库中删除(标记删除) </li></ul></ul><ul><ul><li>从小库中删除(物理删除) </li></ul></ul><ul><li>定期合并小库到大库,并清空小库 </li></ul>
    26. 26. 设计 (7/8) 搜索端索引更新 <ul><li>小库每次同步到一个新的文件夹中 </li></ul><ul><li>保留最近打开的 n (2) 份小库索引目录 </li></ul><ul><li>检测到新的索引到达,关闭一个最旧的,打开新的,预热后标识为可用 </li></ul><ul><li>检测到新的小库到达, reopen 大库(为了逻辑上的简单起见,大小库同步更新) </li></ul>
    27. 27. 设计 (8/8) 新索引预热 <ul><li>目的:消除新打开的索引上前几次搜索慢的问题 </li></ul><ul><li>实现: </li></ul><ul><ul><li>遍历一遍新打开的索引,将数据都读入内存 </li></ul></ul><ul><ul><ul><li>引起 gc ,导致搜索暂停 </li></ul></ul></ul><ul><ul><ul><li>对 lucene 内置的 cache 无贡献 </li></ul></ul></ul><ul><ul><li>搜几个热门的词,并遍历结果集 </li></ul></ul><ul><ul><li>使用原来的 cache 填充新的 cache </li></ul></ul><ul><li>预热完成后,再投入使用 </li></ul>
    28. 28. <ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul><ul><ul><li>目标 </li></ul></ul><ul><ul><li>进度 </li></ul></ul><ul><ul><li>设计 </li></ul></ul><ul><ul><li>实现 </li></ul></ul><ul><ul><li>测试 </li></ul></ul><ul><ul><li>上线,运维 </li></ul></ul><ul><ul><li>经验分享 </li></ul></ul><ul><li>将来:手机之家搜索 V2.0 </li></ul>目录
    29. 29. 实现 (1/8) 架构示意图 端口 1985 IndexRebuilder IndexUpdater Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 IndexReceiver Rebuild xml data Update xml data
    30. 30. 实现 (1/8) 架构示意图 端口 1985 IndexRebuilder IndexUpdater Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 IndexReceiver Rebuild xml data Update xml data
    31. 31. 实现 (2/8) IndexReceiver <ul><li>By Java , Daemon 程序 </li></ul><ul><li>监听端口,使用 SCGI 通讯协议 </li></ul><ul><li>使用 Monkey 为底层 NIO 处理框架 </li></ul><ul><li>接收客户端 post 过来的数据,并写入对应的目录 </li></ul><ul><li>Update 和 rebuild 共用 </li></ul><ul><li>为了保证原子性,先写入 .0.***.xml ,写入完成后,再 rename </li></ul><ul><li>Receiver 只负责写入, updater 和 rebuilder 稍后负责删除(备份) </li></ul><ul><li>对外提供服务,所以尽可能简单,单独进程 </li></ul>
    32. 32. 实现 (1/8) 架构示意图 端口 1985 IndexRebuilder IndexUpdater Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 Rebuild xml data Update xml data
    33. 33. 实现 (3/8) IndexUpdater <ul><li>By Java , Daemon 程序 </li></ul><ul><li>多个索引共用,每个索引起一个线程 </li></ul><ul><li>可根据需要随时停止或启动单个索引更新的线程 </li></ul><ul><li>AddShutdownHook 退出前 close 所有打开的 IndexWriter </li></ul><ul><li>功能: </li></ul><ul><ul><li>更新新数据到当前索引 </li></ul></ul><ul><ul><li>合并大小库 </li></ul></ul><ul><ul><li>拷贝当前索引的快照供搜索使用 </li></ul></ul><ul><ul><li>切换 rebuild 出来的新索引 </li></ul></ul>
    34. 34. 实现 (1/8) 架构示意图 端口 1985 IndexRebuilder Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 Rebuild xml data Update xml data
    35. 35. 实现 (4/8) IndexRebuilder <ul><li>By Java , Daemon 程序 </li></ul><ul><li>多个索引共用,每个索引一个线程 </li></ul><ul><li>重建索引时序图: </li></ul>时间线 rebuilder updater receiver 开始重建 客户端发送开始重建标识 客户端发送重建索引的数据 客户端发送结束重建标识 重建数据接收完毕 重建完成 Receiver 开始抄送 update 数据到 rebuild-update Updater 正常更新 Rebuilder 开始工作 Rebuilder 处理完重建数据 Rebuilder 处理完 t0 到 当前的更新数据,通知 updater ,然后自己退出 Updater 接到通知,切换索引。完成后通知 receiver Receiver 接到通知,停止抄送 updater 数据。 重建过程结束 T0 T1 T2 T3 T4 T5
    36. 36. 实现 (5/8) IndexRebuilder <ul><li>切换索引过程 </li></ul><ul><ul><li>Updater 删除自己当前的索引和未更新完的 xml 文件 </li></ul></ul><ul><ul><li>Updater 将 rebuilder 的索引和 rebuild-update 的 xml 文件 “据为己有” </li></ul></ul><ul><ul><li>通知 receiver 停止抄送 </li></ul></ul><ul><ul><li>继续正常的数据更新过程 </li></ul></ul><ul><li>可以证明这个过程中,不会有数据丢失,也不会有数据重复 </li></ul><ul><ul><li>前提: updater 的 xml 文件和 rebuild-update 的 xml 文件是完全相同的(包括文件名和数据) </li></ul></ul><ul><ul><li>t3-t4 : 数据来自 rebuild-update </li></ul></ul><ul><ul><li>t4-t5 : rebuild-update 中的数据可以被直接忽略 </li></ul></ul>
    37. 37. 实现 (1/8) 架构示意图 端口 1985 Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 Rebuild xml data Update xml data Transfer
    38. 38. 实现 (6/8) Transfer <ul><li>Bash 脚本,每个 indexId 一个进程,由 ControlCenter 或 monitor 启动和停止 </li></ul><ul><li>监控索引快照目录 </li></ul><ul><li>快照目录下存在子目录,并且子目录中存在 copy.done.sign ( IndexUpdater 拷贝快照完成后 touch 的标识),则 rsync 子目录到 search </li></ul><ul><li>Rsync 的时候:先 rsync 大库快照,再 rsync 小库快照,都成功后再 rsync 一个 trans.done.sign </li></ul><ul><li>以 0 字节的 sign 文件作为标识,模拟两阶段提交,保证文件拷贝,传输的原子性 </li></ul>
    39. 39. 实现 (1/8) 架构示意图 端口 1985 Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 Rebuild xml data Update xml data
    40. 40. 实现 (7/8) Searcher <ul><li>By Java , Daemon 程序 </li></ul><ul><li>使用 Monkey 为底层 NIO 处理框架 </li></ul><ul><li>使用 SCGI 通讯协议 </li></ul><ul><li>启动后第一件事: warmUpAllIndex </li></ul><ul><li>当有新索引到达的时候,在后台打开,预热后,再投入使用 </li></ul><ul><li>关闭旧的 IndexSearcher 实例的前提:当前没有线程还在使用它 </li></ul><ul><ul><li>方法:计数 ( get +1 , return -1 ,为 0 表示没有被使用) </li></ul></ul><ul><li>Stat 统计 </li></ul>
    41. 41. 实现 (8/8)Utils <ul><li>Cleaner </li></ul><ul><ul><li>Bash 脚本,每个 indexId 一个进程 </li></ul></ul><ul><ul><li>用来删除 Searcher 已经关闭或跳过的索引 </li></ul></ul><ul><li>Monitor </li></ul><ul><ul><li>监控系统的各个进程是否存在,如不存在,则启动一个新的进程 </li></ul></ul><ul><li>ControlCenter </li></ul><ul><ul><li>Usage: ./controlCenter.sh {start|stop|restart} {all|receiver|updater|rebuilder|searcher|trans|cleaner} </li></ul></ul><ul><ul><li>OR: ./controlCenter.sh {start|stop|restart} {monitor|logSlowSearch} </li></ul></ul><ul><ul><li>OR: ./controlCenter.sh {mkdirs} </li></ul></ul>
    42. 42. <ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul><ul><ul><li>目标 </li></ul></ul><ul><ul><li>进度 </li></ul></ul><ul><ul><li>设计 </li></ul></ul><ul><ul><li>实现 </li></ul></ul><ul><ul><li>测试 </li></ul></ul><ul><ul><li>上线,运维 </li></ul></ul><ul><ul><li>经验分享 </li></ul></ul><ul><li>将来:手机之家搜索 V2.0 </li></ul>目录
    43. 43. 性能测试结果 <ul><li>ab </li></ul><ul><ul><li>-n 1000 -c 10 ( 99% 545ms 100% 32838ms ) </li></ul></ul><ul><ul><li>-n 2000 -c 20 ( 90% 1171ms 99% 4106ms ) </li></ul></ul><ul><ul><ul><li>总请求 3000 ,慢查询比例 4% </li></ul></ul></ul><ul><ul><ul><li>搜索词:手机之家论坛首页的板块名,随机 </li></ul></ul></ul><ul><ul><ul><li>最长: 37s </li></ul></ul></ul><ul><ul><ul><li>> 10s : 22 (索引切换, gc ) </li></ul></ul></ul><ul><ul><ul><li>2s-10s : 38 </li></ul></ul></ul><ul><ul><ul><li>1s-2s : 62 </li></ul></ul></ul>
    44. 44. <ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul><ul><ul><li>目标 </li></ul></ul><ul><ul><li>进度 </li></ul></ul><ul><ul><li>设计 </li></ul></ul><ul><ul><li>实现 </li></ul></ul><ul><ul><li>测试 </li></ul></ul><ul><ul><li>上线,运维 </li></ul></ul><ul><ul><li>经验分享 </li></ul></ul><ul><li>将来:手机之家搜索 V2.0 </li></ul>目录
    45. 45. 部署上线 <ul><li>运行概况 </li></ul><ul><ul><li>updater , rebuilder 部署在 Imobile-SV25-B50 上 </li></ul></ul><ul><ul><ul><li>IntelXeon 4 cpu @2.60GHz , 6G mem </li></ul></ul></ul><ul><ul><ul><li>Slackware 12.1, JDK32 1.6 </li></ul></ul></ul><ul><ul><li>Search 部署在 Imobile-SV39-A49 上: </li></ul></ul><ul><ul><ul><li>X86_64 , 8 cpu @ 2.50GHz , 32G mem </li></ul></ul></ul><ul><ul><ul><li>CentOS release 5.2, JDK64 1.6 </li></ul></ul></ul><ul><ul><li>搜索: 35+ 万查询 / 天,高峰期 > 20 次 /s </li></ul></ul><ul><ul><li>更新: 平均 15 条 / 分钟 </li></ul></ul>
    46. 46. 线上运行观察 <ul><li>Slow search 比例: >1s 1.x%; >2s 0.2% </li></ul><ul><li>机器负载 : 49(search): 1~3; 50(update): <1 </li></ul><ul><li>内存消耗: search: -Xms4096M -Xmx4096M </li></ul><ul><li>Cpu 消耗 :多核之间平均比较分配 </li></ul><ul><li>索引平均更新速度: ~1 分钟 </li></ul><ul><li>索引延迟率(因各种原因导致延迟更新的比例) </li></ul>
    47. 47. <ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul><ul><ul><li>目标 </li></ul></ul><ul><ul><li>进度 </li></ul></ul><ul><ul><li>设计 </li></ul></ul><ul><ul><li>实现 </li></ul></ul><ul><ul><li>测试 </li></ul></ul><ul><ul><li>上线,运维 </li></ul></ul><ul><ul><li>经验分享 </li></ul></ul><ul><li>将来:手机之家搜索 V2.0 </li></ul>目录
    48. 48. 开发中的一些收获 (1/5)‏ <ul><li>FileChannel.transferTo 拷贝文件失败: </li></ul><ul><ul><li>Fewer than the requested number of bytes are transferred if the target channel is non-blocking and it has fewer than count bytes free in its output buffer. </li></ul></ul><ul><ul><li>解决: check copied size ,断点续传 </li></ul></ul><ul><ul><li>根据 lucene 索引文件更新的特性 ( 每次更新一个新版本的时候,都会新建一个全新的文件 ) ,使用 cp -l 链接替代真实的大文件拷贝动作 </li></ul></ul>
    49. 49. 开发中的一些收获 (2/5)‏ <ul><li>Kill 的问题 </li></ul><ul><ul><li>Never kill smart frog, don't kill -9 </li></ul></ul><ul><ul><li>Java use Runtime.getRuntime().addShutdownHook to do the cleaning things </li></ul></ul><ul><ul><li>Lucene IndexWrite need close! </li></ul></ul><ul><ul><li>server 程序,都应该考虑信号捕捉和处理的问题( java 程序容易忽略这个问题) </li></ul></ul>
    50. 50. 开发中的一些收获 (3/5)‏ <ul><li>更新太频繁导致的磁盘 IO 问题 </li></ul><ul><ul><li>同一台机器目录之间同步:没有问题 </li></ul></ul><ul><ul><li>一拖二,一拖三 </li></ul></ul><ul><li>解决 </li></ul><ul><ul><li>建索引的机器不提供搜索服务 </li></ul></ul><ul><ul><li>rsync 限速 </li></ul></ul>
    51. 51. 开发中的一些收获 (4/5)‏ <ul><li>GC 引起的服务暂停 </li></ul><ul><ul><li>多个索引共用 Search 进程 </li></ul></ul><ul><ul><li>每个索引维持了多个 searcher </li></ul></ul><ul><ul><li>索引更新太过频繁: 30 秒 </li></ul></ul><ul><li>解决: </li></ul><ul><ul><li>纵向拆分:将两个最大的库拆分到单独的进程 </li></ul></ul><ul><ul><li>减少 searcher 个数到 2 个 </li></ul></ul><ul><ul><li>谨慎的选择 gc 的类型,并调整 gc 的参数 </li></ul></ul><ul><ul><ul><li>G1 改进不明显,不稳定 </li></ul></ul></ul><ul><ul><ul><li>-XX:+UseParNewGC -XX:ParallelGCThreads=20 -XX:+UseConcMarkSweepGC -XX:SurvivorRatio=8 -XX:TargetSurvivorRatio=90 -XX:MaxTenuringThreshold=31 </li></ul></ul></ul>
    52. 52. 开发中的一些收获 (5/5)‏ <ul><li>Java server 程序的 trouble shooting </li></ul><ul><ul><li>性能问题: jprofile </li></ul></ul><ul><ul><li>内存问题: jmx + jconsole </li></ul></ul><ul><ul><li>线程问题: Thread.currentThread().setName(&quot;diffDetect-&quot; + indexId); ps. Java 线程对传统的 unix 工具不友好 </li></ul></ul><ul><ul><li>详细的 log : log4j </li></ul></ul><ul><ul><li>常用的脚本: logslowsearch.sh </li></ul></ul><ul><ul><li>开发调试阶段:方便的重新编译并重启脚本 </li></ul></ul><ul><ul><li>线上服务阶段:完善的监控及报警机制 </li></ul></ul>
    53. 53. <ul><li>关于手机之家 </li></ul><ul><li>过去:手机之家搜索 V1.0 </li></ul><ul><li>现在:手机之家搜索 V1.5 </li></ul><ul><ul><li>需求背景 </li></ul></ul><ul><ul><li>目标 </li></ul></ul><ul><ul><li>进度 </li></ul></ul><ul><ul><li>设计 </li></ul></ul><ul><ul><li>实现 </li></ul></ul><ul><ul><li>测试 </li></ul></ul><ul><ul><li>上线,运维 </li></ul></ul><ul><ul><li>经验分享 </li></ul></ul><ul><li>将来:手机之家搜索 V2.0 </li></ul>目录
    54. 54. 持续改进 <ul><li>配置文件改动检测,自动重新加载 </li></ul><ul><li>更智能的处理索引字段变更 </li></ul><ul><li>分词算法改进 </li></ul><ul><li>搜索关键字数据挖掘(搜索新词自动发现) </li></ul><ul><li>搜索建议,搜索联想功能 </li></ul><ul><li>排序算法改进 </li></ul><ul><li>整合搜索 </li></ul><ul><li>准实时搜索 </li></ul>
    55. 55. Lucene 3.0 <ul><li>Lucene 2.9 </li></ul><ul><ul><li>Searchable.search(Weight, Filter, Collector): collector 终于可用了 </li></ul></ul><ul><ul><li>Added new MultiReaderHitCollector: 解决 group by </li></ul></ul><ul><ul><li>near real-time search via IndexWriter.getReader(): 单机方案 </li></ul></ul><ul><li>Lucene 3.0 </li></ul><ul><ul><li>Del deprecated apis: 大版本升级要谨慎 </li></ul></ul><ul><ul><li>Port to Java5: 应该会有性能的提升 </li></ul></ul><ul><li>Lucene 3.1 </li></ul><ul><ul><li>Near Realtime Search (using a built in RAMDirectory): 还是单机方案 </li></ul></ul><ul><ul><li>Complete overhaul of FieldCache API/Implementation: 等到花儿也谢了 </li></ul></ul>
    56. 56. 定制功能 <ul><li>在某些情况下作为数据库的替代数据源 </li></ul><ul><ul><li>类似淘宝搜索,按多个字段筛选,过滤,排序 </li></ul></ul><ul><ul><li>当前解决方案:使用 sql 从数据库中选取数据 </li></ul></ul><ul><ul><li>问题:数据可能因为业务逻辑的设计而分散在多个不同的库,表中,联表查询问题,并发压力问题 </li></ul></ul><ul><ul><li>难点:非典型的复杂的查询条件,如 group by </li></ul></ul>
    57. 57. 参考资料 <ul><li>Lucene </li></ul><ul><ul><li>http://lucene.apache.org/ </li></ul></ul><ul><ul><li>http://lucene.apache.org/java/2_4_1/api/index.html </li></ul></ul><ul><li>中文分词 </li></ul><ul><ul><li>http://code.google.com/p/paoding/ </li></ul></ul><ul><ul><li>http://code.google.com/p/imdict-chinese-analyzer/ </li></ul></ul><ul><ul><li>http://code.google.com/p/mmseg4j/ </li></ul></ul><ul><li>Monkey ( Java 底层异步网络 IO 框架) </li></ul><ul><li>DAL </li></ul>
    58. 58. <ul><li>更多讨论 </li></ul><ul><li>关于 imobile </li></ul><ul><ul><li>网站首页 http://www.imobile.com.cn/ </li></ul></ul><ul><ul><li>关于 http://www.imobile.com.cn/about.html </li></ul></ul><ul><li>Longker ( V1.0 版本) </li></ul><ul><ul><li>http://www.longker.org/ </li></ul></ul><ul><li>关于我( V1.5 版本) </li></ul><ul><ul><li>http://www.fulin.org/ </li></ul></ul><ul><ul><li>http://twitter.com/tangfl </li></ul></ul>

    ×