Your SlideShare is downloading. ×
基于 lucene 的站内搜索
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Introducing the official SlideShare app

Stunning, full-screen experience for iPhone and Android

Text the download link to your phone

Standard text messaging rates apply

基于 lucene 的站内搜索

2,701
views

Published on

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

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

Published in: Technology

0 Comments
9 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,701
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
149
Comments
0
Likes
9
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

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

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