基于 lucene 的站内搜索

Loading...

Flash Player 9 (or above) is needed to view presentations.
We have detected that you do not have it on your computer. To install it, go here.

0 comments

Post a comment

    Post a comment
    Embed Video
    Edit your comment Cancel

    Notes on slide 1

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

    4 Favorites

    基于 lucene 的站内搜索 - Presentation Transcript

    1. 基于 lucene 的站内搜索 tangfulin <tangfulin@gmail.com> www.imobile.com.cn
      • 关于手机之家
      • 过去:手机之家搜索 V1.0
      • 现在:手机之家搜索 V1.5
        • 需求背景
        • 目标
        • 进度
        • 设计
        • 实现
        • 测试
        • 上线,运维
        • 经验分享
      • 将来:手机之家搜索 V2.0
      目录
      • 关于手机之家
      • 过去:手机之家搜索 V1.0
      • 现在:手机之家搜索 V1.5
        • 需求背景
        • 目标
        • 进度
        • 设计
        • 实现
        • 测试
        • 上线,运维
        • 经验分享
      • 将来:手机之家搜索 V2.0
      目录
    2. 关于手机之家 (1/2)‏
    3. 关于手机之家 (2/2)‏
        • 手机之家是一个旨在提供全方位的手机相关服务的资讯类网站。在 7 年的
        • 时间里,手机之家从无到有,已经发展成为极具人气、最受关注的手机产
        • 品资讯网站。
        • 目前已有的一些统计数据:
        • a. 1000w+ 用户
        • b. 3000w+ 帖子
        • c. 1.1TB+ 附件
        • d. 780w+ Page View/ 每天
        • e. 5~10w 在线用户 /15 分钟
      • 关于手机之家
      • 过去:手机之家搜索 V1.0
      • 现在:手机之家搜索 V1.5
        • 需求背景
        • 目标
        • 进度
        • 设计
        • 实现
        • 测试
        • 上线,运维
        • 经验分享
      • 将来:手机之家搜索 V2.0
      目录
      • 产品大全搜索
      • 新闻 CMS 搜索
      • 论坛搜索(默认只搜索标题)
      • 论坛帖子及回复搜索
      • 手机铃声,主题,电子书,软件搜索
      • 二手交易搜索
      • 。。。
      手机之家的搜索 V1.0(1/3)‏
    4. 手机之家的搜索 V1.0(2/3)‏
      • 实现了多个业务模块需要的搜索功能
        • 不同的搜索字段
        • 不同的排序方式
        • 不同的更新频率
        • Java 多进程,多线程实现
    5. 手机之家的搜索 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 条 / 分钟
      • 关于手机之家
      • 过去:手机之家搜索 V1.0
      • 现在:手机之家搜索 V1.5
        • 需求背景
        • 目标
        • 进度
        • 设计
        • 实现
        • 测试
        • 上线,运维
        • 经验分享
      • 将来:手机之家搜索 V2.0
      目录
      • 关于手机之家
      • 过去:手机之家搜索 V1.0
      • 现在:手机之家搜索 V1.5
        • 需求背景
        • 目标
        • 进度
        • 设计
        • 实现
        • 测试
        • 上线,运维
        • 经验分享
      • 将来:手机之家搜索 V2.0
      目录
    6. 需求背景 (1/3)‏
      • 重建索引
        • 索引字段变更
        • 分词算法变更
        • 搜索结果异常(记录重复,记录丢失)
        • 索引文件意外损坏
        • V1.0 :手工重建,人工参与重建过程,重建过程中不能正常更新
        • V1.5 :自动重建,重建过程中正常更新原来的索引
    7. 需求背景 (2/3)‏
      • 缩短更新周期(及时更新)
        • Google 索引 imobile 更新周期为 30 分钟
        • V1.0 索引更新周期为 15 分钟
        • V1.5 预期更新周期为 3 分钟,实际为 1-5 分钟
    8. 需求背景 (3/3)‏
      • 搜索大索引( V1.5 )
        • 3000+ 万条记录的一个库, xml 原始文件 14G
        • V1.0 索引文件为 13 G ,无法快速更新
        • V1.5 索引文件为 3.9G (还是无法快速更新?)
        • V1.5 完整重建一次: 140 分钟
      • 关于手机之家
      • 过去:手机之家搜索 V1.0
      • 现在:手机之家搜索 V1.5
        • 需求背景
        • 目标
        • 进度
        • 设计
        • 实现
        • 测试
        • 上线,运维
        • 经验分享
      • 将来:手机之家搜索 V2.0
      目录
    9. 目标
      • 及时更新( 3 分钟)
      • 快速重建( < 2 小时)
      • 可配置(拥抱需求变化)
      • 可监控(运维友好)
      • SLA : always 可写, always 可读,异常的时候唯一的表现是更新延迟
      • 高性能,能承受较大的流量,并发压力
      • 关于手机之家
      • 过去:手机之家搜索 V1.0
      • 现在:手机之家搜索 V1.5
        • 需求背景
        • 目标
        • 进度
        • 设计
        • 实现
        • 测试
        • 上线,运维
        • 经验分享
      • 将来:手机之家搜索 V2.0
      目录
    10. 进度
      • 2009 年 4 月 1 号 search 2.0 init (节日快乐!)
      • 4 月 12 号,修改版本号为 1.5
      • 6 月 1 号, search 1.5 在线上试运行 (节日快乐 again !)
      • 关于手机之家
      • 过去:手机之家搜索 V1.0
      • 现在:手机之家搜索 V1.5
        • 需求背景
        • 目标
        • 进度
        • 设计
        • 实现
        • 测试
        • 上线,运维
        • 经验分享
      • 将来:手机之家搜索 V2.0
      目录
    11. 设计 (1/8)‏
      • 分离索引与存储,二次读取
      • 分离读与写
      • 分离 update 和 rebuild
      • 拆分大库和小库
      • new open 小库(小库滚动), reopen 大库
      • 新索引预热
      • 更多: http://blog.fulin.org/category/tech/lucene
    12. 设计 (2/8) 分离索引与存储,二次读取
      • 索引里只存储 id ,其他的字段只索引不存储。
      • 优点:
        • 保持索引的大小为一个可接受的范围
        • 提高索引读取速度
        • 提高索引 cache 效率
      • 缺点:搜索时需要额外的请求来获取其它必须的字段( lucene + db 方案)
      • 衍生项目: blackdb , memcache 协议 + bdbJE 存储
    13. 设计 (3/8) 分离读与写
      • 优点:
        • 降低编程复杂度
        • 保证搜索服务的可用性,和可扩展性(可以将索引文件分发到多台机器上,同时对外提供服务)
        • 提升索引更新速度
      • 缺点:
        • 需要移动索引文件
        • 需要额外的索引更新逻辑( reopen )
        • 无法使用当前设计中的 lucene 的 real-time search
    14. 设计 (4/8) 分离 update 和 rebuild
      • Rebuild 的同时, update 正常更新
      • Rebuild 需要将重建这段时间的更新计入新的索引中
      • Rebuild 完成后,通知 update 切换到新索引上来,并继续更新
      • 进程间通信,当前使用最原始的基于文件的方式
    15. 设计 (5/8) 拆分大库和小库
      • 保证及时更新的同时,减少索引频繁同步(由写索引同步到读索引)带来的 io 压力
      • 更新频率
        • 小库(最近更新库) 1 分钟
        • 大库(历史库) 1 天到 1 周,可配置
      • 并行搜索,加速搜索速度
      • 问题: group by
    16. 设计 (6/8) 拆分大库和小库(续)
      • 增加新记录:
        • 增加到小库
      • 更新记录:
        • 从大库中删除(标记删除)
        • 从小库中删除(物理删除)
        • 增加到小库
      • 删除记录
        • 从大库中删除(标记删除)
        • 从小库中删除(物理删除)
      • 定期合并小库到大库,并清空小库
    17. 设计 (7/8) 搜索端索引更新
      • 小库每次同步到一个新的文件夹中
      • 保留最近打开的 n (2) 份小库索引目录
      • 检测到新的索引到达,关闭一个最旧的,打开新的,预热后标识为可用
      • 检测到新的小库到达, reopen 大库(为了逻辑上的简单起见,大小库同步更新)
    18. 设计 (8/8) 新索引预热
      • 目的:消除新打开的索引上前几次搜索慢的问题
      • 实现:
        • 遍历一遍新打开的索引,将数据都读入内存
          • 引起 gc ,导致搜索暂停
          • 对 lucene 内置的 cache 无贡献
        • 搜几个热门的词,并遍历结果集
        • 使用原来的 cache 填充新的 cache
      • 预热完成后,再投入使用
      • 关于手机之家
      • 过去:手机之家搜索 V1.0
      • 现在:手机之家搜索 V1.5
        • 需求背景
        • 目标
        • 进度
        • 设计
        • 实现
        • 测试
        • 上线,运维
        • 经验分享
      • 将来:手机之家搜索 V2.0
      目录
    19. 实现 (1/8) 架构示意图 端口 1985 IndexRebuilder IndexUpdater Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 IndexReceiver Rebuild xml data Update xml data
    20. 实现 (1/8) 架构示意图 端口 1985 IndexRebuilder IndexUpdater Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 IndexReceiver Rebuild xml data Update xml data
    21. 实现 (2/8) IndexReceiver
      • By Java , Daemon 程序
      • 监听端口,使用 SCGI 通讯协议
      • 使用 Monkey 为底层 NIO 处理框架
      • 接收客户端 post 过来的数据,并写入对应的目录
      • Update 和 rebuild 共用
      • 为了保证原子性,先写入 .0.***.xml ,写入完成后,再 rename
      • Receiver 只负责写入, updater 和 rebuilder 稍后负责删除(备份)
      • 对外提供服务,所以尽可能简单,单独进程
    22. 实现 (1/8) 架构示意图 端口 1985 IndexRebuilder IndexUpdater Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 Rebuild xml data Update xml data
    23. 实现 (3/8) IndexUpdater
      • By Java , Daemon 程序
      • 多个索引共用,每个索引起一个线程
      • 可根据需要随时停止或启动单个索引更新的线程
      • AddShutdownHook 退出前 close 所有打开的 IndexWriter
      • 功能:
        • 更新新数据到当前索引
        • 合并大小库
        • 拷贝当前索引的快照供搜索使用
        • 切换 rebuild 出来的新索引
    24. 实现 (1/8) 架构示意图 端口 1985 IndexRebuilder Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 Rebuild xml data Update xml data
    25. 实现 (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
    26. 实现 (5/8) IndexRebuilder
      • 切换索引过程
        • Updater 删除自己当前的索引和未更新完的 xml 文件
        • Updater 将 rebuilder 的索引和 rebuild-update 的 xml 文件 “据为己有”
        • 通知 receiver 停止抄送
        • 继续正常的数据更新过程
      • 可以证明这个过程中,不会有数据丢失,也不会有数据重复
        • 前提: updater 的 xml 文件和 rebuild-update 的 xml 文件是完全相同的(包括文件名和数据)
        • t3-t4 : 数据来自 rebuild-update
        • t4-t5 : rebuild-update 中的数据可以被直接忽略
    27. 实现 (1/8) 架构示意图 端口 1985 Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 Rebuild xml data Update xml data Transfer
    28. 实现 (6/8) Transfer
      • Bash 脚本,每个 indexId 一个进程,由 ControlCenter 或 monitor 启动和停止
      • 监控索引快照目录
      • 快照目录下存在子目录,并且子目录中存在 copy.done.sign ( IndexUpdater 拷贝快照完成后 touch 的标识),则 rsync 子目录到 search
      • Rsync 的时候:先 rsync 大库快照,再 rsync 小库快照,都成功后再 rsync 一个 trans.done.sign
      • 以 0 字节的 sign 文件作为标识,模拟两阶段提交,保证文件拷贝,传输的原子性
    29. 实现 (1/8) 架构示意图 端口 1985 Searcher 配置文件 DAL 数据更新 同步通知搜索 搜索客户端调用 Searcher 的 API 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 端口 1986 Rebuild xml data Update xml data
    30. 实现 (7/8) Searcher
      • By Java , Daemon 程序
      • 使用 Monkey 为底层 NIO 处理框架
      • 使用 SCGI 通讯协议
      • 启动后第一件事: warmUpAllIndex
      • 当有新索引到达的时候,在后台打开,预热后,再投入使用
      • 关闭旧的 IndexSearcher 实例的前提:当前没有线程还在使用它
        • 方法:计数 ( get +1 , return -1 ,为 0 表示没有被使用)
      • Stat 统计
    31. 实现 (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}
      • 关于手机之家
      • 过去:手机之家搜索 V1.0
      • 现在:手机之家搜索 V1.5
        • 需求背景
        • 目标
        • 进度
        • 设计
        • 实现
        • 测试
        • 上线,运维
        • 经验分享
      • 将来:手机之家搜索 V2.0
      目录
    32. 性能测试结果
      • 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
      • 关于手机之家
      • 过去:手机之家搜索 V1.0
      • 现在:手机之家搜索 V1.5
        • 需求背景
        • 目标
        • 进度
        • 设计
        • 实现
        • 测试
        • 上线,运维
        • 经验分享
      • 将来:手机之家搜索 V2.0
      目录
    33. 部署上线
      • 运行概况
        • 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 条 / 分钟
    34. 线上运行观察
      • Slow search 比例: >1s 1.x%; >2s 0.2%
      • 机器负载 : 49(search): 1~3; 50(update): <1
      • 内存消耗: search: -Xms4096M -Xmx4096M
      • Cpu 消耗 :多核之间平均比较分配
      • 索引平均更新速度: ~1 分钟
      • 索引延迟率(因各种原因导致延迟更新的比例)
      • 关于手机之家
      • 过去:手机之家搜索 V1.0
      • 现在:手机之家搜索 V1.5
        • 需求背景
        • 目标
        • 进度
        • 设计
        • 实现
        • 测试
        • 上线,运维
        • 经验分享
      • 将来:手机之家搜索 V2.0
      目录
    35. 开发中的一些收获 (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 链接替代真实的大文件拷贝动作
    36. 开发中的一些收获 (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 程序容易忽略这个问题)
    37. 开发中的一些收获 (3/5)‏
      • 更新太频繁导致的磁盘 IO 问题
        • 同一台机器目录之间同步:没有问题
        • 一拖二,一拖三
      • 解决
        • 建索引的机器不提供搜索服务
        • rsync 限速
    38. 开发中的一些收获 (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
    39. 开发中的一些收获 (5/5)‏
      • Java server 程序的 trouble shooting
        • 性能问题: jprofile
        • 内存问题: jmx + jconsole
        • 线程问题: Thread.currentThread().setName(&quot;diffDetect-&quot; + indexId); ps. Java 线程对传统的 unix 工具不友好
        • 详细的 log : log4j
        • 常用的脚本: logslowsearch.sh
        • 开发调试阶段:方便的重新编译并重启脚本
        • 线上服务阶段:完善的监控及报警机制
      • 关于手机之家
      • 过去:手机之家搜索 V1.0
      • 现在:手机之家搜索 V1.5
        • 需求背景
        • 目标
        • 进度
        • 设计
        • 实现
        • 测试
        • 上线,运维
        • 经验分享
      • 将来:手机之家搜索 V2.0
      目录
    40. 持续改进
      • 配置文件改动检测,自动重新加载
      • 更智能的处理索引字段变更
      • 分词算法改进
      • 搜索关键字数据挖掘(搜索新词自动发现)
      • 搜索建议,搜索联想功能
      • 排序算法改进
      • 整合搜索
      • 准实时搜索
    41. 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: 等到花儿也谢了
    42. 定制功能
      • 在某些情况下作为数据库的替代数据源
        • 类似淘宝搜索,按多个字段筛选,过滤,排序
        • 当前解决方案:使用 sql 从数据库中选取数据
        • 问题:数据可能因为业务逻辑的设计而分散在多个不同的库,表中,联表查询问题,并发压力问题
        • 难点:非典型的复杂的查询条件,如 group by
    43. 参考资料
      • 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
      • 更多讨论
      • 关于 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
    SlideShare Zeitgeist 2009

    + fulin tangfulin tang Nominate

    custom

    372 views, 4 favs, 1 embeds more stats

    imobile 基于 lucene 的站内搜索, tangfulin more

    More info about this document

    © All Rights Reserved

    Go to text version

    • Total Views 372
      • 364 on SlideShare
      • 8 from embeds
    • Comments 0
    • Favorites 4
    • Downloads 23
    Most viewed embeds
    • 8 views on http://blog.fulin.org

    more

    All embeds
    • 8 views on http://blog.fulin.org

    less

    Flagged as inappropriate Flag as inappropriate
    Flag as inappropriate

    Select your reason for flagging this presentation as inappropriate. If needed, use the feedback form to let us know more details.

    Cancel
    File a copyright complaint
    Having problems? Go to our helpdesk?

    Categories