狠狠撸

狠狠撸Share a Scribd company logo
基于 lucene 的站内搜索实战


      Beta 技术沙龙
           http://club.blogbeta.com
          官方 twitter : @betasalon

 tangfulin <tangfulin@gmail.com>
 www.imobile.com.cn
 2009.07.26
目录
   对于手机之家
   过去:手机之家搜索 V1.0
   现在:手机之家搜索 V1.5
       需求背景
       目标
       进度
       设计
       实现
       测试
       上线,运维
       经验分享
   将来:手机之家搜索 V2.0
目录
   对于手机之家
   过去:手机之家搜索 V1.0
   现在:手机之家搜索 V1.5
       需求背景
       目标
       进度
       设计
       实现
       测试
       上线,运维
       经验分享
   将来:手机之家搜索 V2.0
基于尝耻肠别苍别的站内搜索 Beta
对于手机之家

手机之家是一个旨在提供全方位的手机相关服务的资讯类网站。在 7 年的

时间里,手机之家从无到有,已经发展成为极具人气、最受关注的手机产

品资讯网站。



目前已有的一些统计数据:

●a. 1100w+ 用户
●b. 3000w+ 帖子

●c. 1.1TB+ 附件

●d. 780w+ Page View/ 每天

●e. 5~10w 在线用户 /15 分钟
目录
   对于手机之家
   过去:手机之家搜索 V1.0
   现在:手机之家搜索 V1.5
       需求背景
       目标
       进度
       设计
       实现
       测试
       上线,运维
       经验分享
   将来:手机之家搜索 V2.0
手机之家的搜索 V1.0(1/3)
   产物大全搜索
   新闻 CMS? 搜索
   论坛搜索(默认只搜索标题)
   论坛帖子及回复搜索
   手机铃声,主题,电子书,软件搜索
   二手交易搜索
   其它版块的搜索
手机之家的搜索 V1.0(2/3)
?
    基本实现了多个业务模块需要的搜索功能
    ?
        不同的搜索字段
    ?
        不同的排序方式
    ?
        不同的更新频率
    ?
        Java 多进程,多线程实现
手机之家的搜索 V1.0(3/3)
?   运行概况
    ?   Dev by chaoqian (http://www.longker.org/)
    ?   最初基于 Lucene 2.2 ,当前 2.4.1
    ?   开发时间: 07 年 12 月- 08 年 4 月
    ?   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
需求背景 (1/3)
?
    重建索引
    ?
        索引字段变更
    ?
        分词算法变更
    ?
        搜索结果异常(记录重复,记录丢失)
    ?
        索引文件意外损坏
    ?
        V1.0 :半手工重建,重建过程需人工参与,重建过程中
        不能正常更新
    ?
        V1.5 :自动重建,重建过程中正常更新原来的索引
需求背景 (2/3)
?
    缩短更新周期(及时更新)
    ?
        Google 更新手机之家内容的周期为 30 分钟左右
    ?
        V1.0 索引更新周期为 10 - 15 分钟左右
    ?
        V1.5 预期更新周期为 3 分钟,实际为 1-5 分钟
需求背景 (3/3)
?   搜索大索引( V1.5 )
    ?   3300+ 万条记录的一个库, xml 原始文件 14G
    ?   V1.0 索引文件为 13 G ,无法快速更新
    ?   V1.5 索引文件为 3.9G (还是无法快速更新?)
    ?   V1.5 完整重建一次: 140 分钟
目录
   对于手机之家
   过去:手机之家搜索 V1.0
   现在:手机之家搜索 V1.5
       需求背景
       目标
       进度
       设计
       实现
       测试
       上线,运维
       经验分享
   将来:手机之家搜索 V2.0
目标
?
    及时更新( 3 分钟)
?
    快速重建( < 2 小时)
?
    可配置(拥抱需求变化)
?
    可监控(运维友好)
?
    SLA :永远可写,永远可读,异常的时候唯一的表现是
    更新延迟
?
    高性能,能承受较大的流量,并发压力
目录
   对于手机之家
   过去:手机之家搜索 V1.0
   现在:手机之家搜索 V1.5
       需求背景
       目标
       进度
       设计
       实现
       测试
       上线,运维
       经验分享
   将来:手机之家搜索 V2.0
进度
?
    2009 年 4 月 1 号 search 2.0 init
?
    4 月 12 号,修改版本号为 1.5
?
    6 月 1 号, search 1.5 在线上试运行
?
    6 月 22 号,正式替换原来的搜索进程
目录
   对于手机之家
   过去:手机之家搜索 V1.0
   现在:手机之家搜索 V1.5
       需求背景
       目标
       进度
       设计
       实现
       测试
       上线,运维
       经验分享
   将来:手机之家搜索 V2.0
设计 (1/8)
?
    分离索引与存储,二次读取
?
    分离读与写
?
    分离 update 和 rebuild
?
    拆分大库和小库
?
    new open 小库(小库滚动), reopen 大库
?
    新索引预热
?
    更多: http://blog.fulin.org/category/tech/lucene
设计 (2/8) 分离索引与存储,二次读取
?   索引里只存储 id ,其他的字段只索引不存储。
?   优点:
    ?   保持索引的大小为一个可接受的范围
    ?   提高索引读取速度
    ?   提高索引 cache 效率
?   缺点:搜索时需要额外的请求来获取其它必须的字段
    ( lucene + db 方案)
?   衍生项目: blackdb , memcache 协议 + bdbJE 存储
设计 (3/8) 分离读与写
?
    优点:
    ?
        降低编程复杂度
    ?
        保证搜索服务的可用性,和可扩展性(可以将索引文件
        分发到多台机器上,同时对外提供服务)
    ?
        提升索引更新速度
?
    缺点:
    ? 需要移动索引文件
    ? 需要额外的索引更新逻辑( reopen )
    ? 无法使用当前设计中的 lucene 的 real-time search
设计 (4/8) 分离       update 和 rebuild

?
    Rebuild 的同时, update 正常更新
?
    Rebuild 需要将重建这段时间的更新计入新的索引中
?
    Rebuild 完成后,通知 update 切换到新索引上来,并
    继续更新
?
    进程间通信,当前使用最原始的基于文件的方式
设计 (5/8) 拆分大库和小库
?
    保证及时更新的同时,减少索引频繁同步(由写索引同
    步到读索引)带来的 io 压力
?
    更新频率
    ? 小库(最近更新库) 1 分钟
    ? 大库(历史库) 1 天到 1 周,可配置
?
    并行搜索,加速搜索速度
?
    问题: group by
设计 (6/8) 拆分大库和小库(续)
?
    增加新记录:
    ?
        增加到小库
?
    更新记录:
    ?
        从大库中删除(标记删除)
    ?
        从小库中删除(物理删除)
    ?
        增加到小库
?
    删除记录
    ?
        从大库中删除(标记删除)
    ?
        从小库中删除(物理删除)
?
    定期合并小库到大库,并清空小库
设计 (7/8) 搜索端索引更新
?
    小库每次同步到一个新的文件夹中
?
    保留最近打开的 n (2) 份小库索引目录
?
    检测到新的索引到达,关闭一个最旧的,打开新的,预
    热后标识为可用
?
    检测到新的小库到达, reopen 大库(为了逻辑上的简
    单起见,大小库同步更新)
设计 (8/8) 新索引预热
?
    目的:消除新打开的索引上前几次搜索慢的问题
?
    实现:
    ? 过去:遍历一遍新打开的索引,将数据都读入内存
     ? 引起 gc ,导致搜索暂停
     ? 对 lucene 内置的 cache 无贡献
    ? 现在:搜几个热门的词,并遍历结果集
    ? 将来:使用原来的 cache 填充新的 cache
?
    预热完成后,再投入使用
目录
   对于手机之家
   过去:手机之家搜索 V1.0
   现在:手机之家搜索 V1.5
       需求背景
       目标
       进度
       设计
       实现
       测试
       上线,运维
       经验分享
   将来:手机之家搜索 V2.0
实现 (1/8)
                                         IndexRebuilder
    搜索管理后台
 发出开始重建索引命令         IndexReceiver
  cron 发送重建数据
                              Rebuild
                              xml data
                    端口
                    1986
                               Update
                              xml data   IndexUpdater

  DAL 数据更新                                                配置文件
  同步通知搜索


                   Searcher

  搜索客户端调用
  Searcher 的 API     端口
                     1985
实现 (2/8)IndexReceiver
                                          IndexRebuilder
     搜索管理后台        IndexReceiver
  发出开始重建索引命令
   cron 发送重建数据
                               Rebuild
                               xml data
                      端口
                      1986
                                Update
                               xml data   IndexUpdater

   DAL 数据更新                                                配置文件
   同步通知搜索


                    Searcher

  搜索客户端调用
  Searcher 的 API      端口
                      1985
实现 (2/8)IndexReceiver
?
    By Java , Daemon 程序
?
    监听端口,使用 SCGI 通讯协议
?
    使用 Monkey 为底层 NIO 处理框架
?
    接收客户端 post 过来的数据,并写入对应的目录
?
    Update 和 rebuild 共用
?
    为了保证原子性,先写入 .0.***.xml ,写入完成后,再 rename
?
    Receiver 只负责写入, updater 和 rebuilder 稍后负责删除(备份)
?
    对外提供服务,所以尽可能简单,单独进程
实现 (3/8)IndexUpdater
                                         IndexRebuilder
     搜索管理后台
  发出开始重建索引命令
   cron 发送重建数据
                              Rebuild
                              xml data
                    端口
                    1986
                               Update
                                         IndexUpdater
                              xml data

   DAL 数据更新                                               配置文件
   同步通知搜索


                   Searcher

  搜索客户端调用
  Searcher 的 API     端口
                     1985
实现 (3/8)IndexUpdater
?
    By Java , Daemon 程序
?
    多个索引共用,每个索引起一个线程
?
    可根据需要随时停止或启动单个索引更新的线程
?
    AddShutdownHook 退出前 close 所有打开的 IndexWriter
?
    功能:
    ? 更新新数据到当前索引
    ? 合并大小库
    ? 拷贝当前索引的快照供搜索使用
    ? 切换 rebuild 出来的新索引
实现 (4/8)IndexRebuilder
                                     IndexRebuilder

     搜索管理后台
  发出开始重建索引命令
   cron 发送重建数据
                              Rebuild
                              xml data
                    端口
                    1986
                               Update
                              xml data

   DAL 数据更新                                           配置文件
   同步通知搜索


                   Searcher

  搜索客户端调用
  Searcher 的 API     端口
                     1985
实现 (4/8)IndexRebuilder
?
     By Java , Daemon 程序
?
     多个索引共用,每个索引一个线程
?
     重建索引时序图:
                                                                 Receiver 接到通
                                                                 知,停止抄送
                                                                 updater 数据。
客户端发送开                 客户端发送重   客户端发送结                           重建过程结束
始重建标识                  建索引的数据   束重建标识

         Receiver 开始抄送
         update 数据到                                                              receiver
         rebuild-update
                                                            Updater 接到
          Updater 正常                                        通知,切换索
    T0




                                  T1


                                         T2


                                                  T3

                                                       T4




                                                                         T5
          更新                                                引。完成后通               updater
                                                            知 receiver

          Rebuilder                       Rebuilder    Rebuilder 处理完 t0
          开始工作                            处理完重         到 当前的更新数据,               rebuilder
                                          建数据          通知 updater ,然后
                                                       自己退出
开始重建                            重建数据            重建完成                            时间线
                                接收完毕
实现 (5/8)IndexRebuilder
?
    切换索引过程
    ? Updater 删除自己当前的索引和未更新完的 xml 文件
    ? Updater 将 rebuilder 的索引和 rebuild-update 的 xml 文件 “据为己有”
    ? 通知 receiver 停止抄送
    ? 继续正常的数据更新过程
?
    可以证明这个过程中,不会有数据丢失,也不会有数据重复
    ? 前提: updater 的 xml 文件和 rebuild-update 的 xml 文件是完全相
      同的(包括文件名和数据)
    ? t3-t4 : 数据来自 rebuild-update
    ? t4-t5 : rebuild-update 中的数据可以被直接忽略
实现 (6/8)Transfer

     搜索管理后台
  发出开始重建索引命令
   cron 发送重建数据
                              Rebuild
                              xml data
                    端口
                    1986
                               Update
                              xml data

   DAL 数据更新                                     配置文件
   同步通知搜索


                   Searcher              Transfer
  搜索客户端调用
  Searcher 的 API     端口
                     1985
实现 (6/8)Transfer
?
    Bash 脚本,每个 indexId 一个进程,由 ControlCenter 或 monitor 启
    动和停止
?
    监控索引快照目录
?
    快照目录下存在子目录,并且子目录中存在 copy.done.sign
    ( IndexUpdater 拷贝快照完成后 touch 的标识),则 rsync 子目录到
    search
?
    Rsync 的时候:先 rsync 大库快照,再 rsync 小库快照,都成功后再
    rsync 一个 trans.done.sign
?
    以 0 字节的 sign 文件作为标识,模拟两阶段提交,保证文件拷贝,
    传输的原子性
实现 (7/8)Searcher

     搜索管理后台
  发出开始重建索引命令
   cron 发送重建数据
                           Rebuild
                           xml data
                    端口
                    1986
                            Update
                           xml data

   DAL 数据更新                           配置文件
   同步通知搜索

                   Searcher

  搜索客户端调用
  Searcher 的 API    端口
                    1985
实现 (7/8)Searcher
?
    By Java , Daemon 程序
?
    使用 Monkey 为底层 NIO 处理框架
?
    使用 SCGI 通讯协议
?
    启动后第一件事: warmUpAllIndex
?
    当有新索引到达的时候,在后台打开,预热后,再投入使用
?
    关闭旧的 IndexSearcher 实例的前提:当前没有线程还在使用它
    ? 方法:计数 ( get +1 , return -1 ,为 0 表示没有被使用)
?
    Stat 统计
实现 (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
性能简单测试结果
?   Apache?bench
    ?   ?n?1000??c?10?? ( 99%????545ms?????100%??32838ms )
    ?   ?n?2000??c?20?? ( 90%???1171ms????99%???4106ms )
          ?   库大小: 4.1G 条目数: 3300+w 更新周期: 1 分钟
          ?   总请求 3000 ,慢查询 ( 耗时大于 1 秒 ) 比例 4%
          ?
              搜索词:手机之家论坛首页的板块名,随机
          ?
              最长: 37s
          ?   >?10s?:?22? (索引切换, gc )
          ?   2s?10s?:?38
          ?   1s?2s?:?62
性能对比测试结果 (1/6)
?   Apache?bench
    ?   库大小: 4.1G ,条目数: 3300+w ,更新周期: 1 分钟
    ?   搜索词:手机之家论坛板块名随机
    ?   对比条件
          ?   停止更新与正常更新
          ?   分配索引 1 倍大小的内存与 2 倍大小的内存
          ?   并发 10 个与 20 个
    ?   Document?Length:?????1529?bytes
    ?   Total?transferred:???????3447737?bytes?(1722053?bytes)
    ?   HTML?transferred:????3085737?bytes?(1541053?bytes)
性能对比测试结果 (2/6)
Time taken for tests                        停止更新 正常更新
分配索引大小1倍内存             ab -n 2000 -c   20    21.85 64.17
分配索引大小1倍内存             ab -n 1000 -c   10     13.1 11.93
分配索引大小2倍内存             ab -n 2000 -c   20     22.8 22.89
分配索引大小2倍内存             ab -n 1000 -c   10    10.37 10.74

备注:单位为秒
性能对比测试结果 (3/6)
Requests per second             停止更新 正常更新
分配索引大小1倍内存 ab -n 2000 -c   20    91.52 31.17
分配索引大小1倍内存 ab -n 1000 -c   10    76.33 83.83
分配索引大小2倍内存 ab -n 2000 -c   20    87.71 87.39
分配索引大小2倍内存 ab -n 1000 -c   10    96.45 93.13
性能对比测试结果 (4/6)
Time per request                         停止更新      正常更新
                                         218.531   641.674
分配索引大小1倍内存 ab -n 2000 -c 20              10.927    32.084
                                         131.015   119.288
分配索引大小1倍内存 ab -n 1000 -c 10              13.102    11.929
                                         228.012   228.870
分配索引大小2倍内存 ab -n 2000 -c 20              11.401    11.444
                                         103.676   107.375
分配索引大小2倍内存 ab -n 1000 -c 10              10.368    10.738
备注:
[ms] (mean)
(mean, across all concurrent requests)
性能对比测试结果 (5/6)
Transfer rate                          停止更新 正常更新
分配索引大小1倍内存        ab -n 2000 -c   20    154.06  52.47
分配索引大小1倍内存        ab -n 1000 -c   10    128.46 140.98
分配索引大小2倍内存        ab -n 2000 -c   20    147.63 146.82
分配索引大小2倍内存        ab -n 1000 -c   10    162.07 156.39
备注:
(Kbytes/sec)
性能对比测试结果 (6/6)
耗时比例                          停止更新 正常更新
                              50%  59 50% 162
                              95% 905 90% 1403
分配索引大小1倍内存 ab -n 2000 -c 20   100% 1525 98% 5738
                              50%  34 50%    24
                              99% 978 98% 750
分配索引大小1倍内存 ab -n 1000 -c 10   100% 1420 100% 3600
                              50%  61 50%    41
                              95% 906 95% 988
分配索引大小2倍内存 ab -n 2000 -c 20   99% 1519 99% 1678
                              50%  28 50%    27
                              99% 744 99% 698
分配索引大小2倍内存 ab -n 1000 -c 10   100% 905 100% 764

备注:百分比 毫秒
目录
   对于手机之家
   过去:手机之家搜索 V1.0
   现在:手机之家搜索 V1.5
       需求背景
       目标
       进度
       设计
       实现
       测试
       上线,运维
       经验分享
   将来:手机之家搜索 V2.0
部署上线
?   运行概况
    ?   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 条 / 分钟
生产环境运行观察
?   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
开发中的一些收获 (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 链接替代真实的
        大文件拷贝动作
开发中的一些收获 (2/5)
?   Kill? 的问题
    ?   Never?kill?smart?frog,?don't?kill??9
    ?   Java?use?Runtime.getRuntime().addShutdownHook??to?do?the?cleaning?
        things
    ?   Lucene?IndexWriter?need?close!
    ?   server? 程序,都应该考虑信号捕捉和处理的问题( java? 程序容易忽
        略这个问题)
开发中的一些收获 (3/5)
?
    更新太频繁导致的磁盘 IO 问题
    – 同一台机器目录之间同步:没有问题
    – 一拖二,一拖三
?
    暂时解决
    – 建索引的机器不提供搜索服务
    – rsync 限速
开发中的一些收获 (4/5)
?   GC? 引起的服务暂停
    ?
        多个索引共用 Search 进程
    ?
        每个索引维持了多个 searcher
    ?
        索引更新太过频繁: 30 秒
?   暂时解决
    ?
        纵向拆分:将两个最大的库拆分到单独的进程
    ?
        减少 searcher 个数到 2? 个
    ?
        谨慎的选择 gc 的类型,并调整 gc 的参数
         ?   G1 改进不明显,不稳定
开发中的一些收获 (5/5)
?   Java?server? 程序的 trouble?shooting
    ?   性能问题: jprofile
    ?   内存问题: jmx? + jconsole
    ?   线程问题: Thread.currentThread().setName("diffDetect?"?+?
        indexId);?
    ?
        详细的 log : log4j
    ?
        常用的脚本: logslowsearch.sh
    ?
        开发调试阶段:方便的重新编译并重启脚本
    ?
        线上服务阶段:完善的监控及报警机制
目录
   对于手机之家
   过去:手机之家搜索 V1.0
   现在:手机之家搜索 V1.5
       需求背景
       目标
       进度
       设计
       实现
       测试
       上线,运维
       经验分享
   将来:手机之家搜索 V2.0
持续改进
?
    配置文件改动检测,自动重新加载
?
    更智能的处理索引字段变更
?
    分词算法改进
?
    搜索关键字数据挖掘(搜索新词自动发现)
?
    搜索建议,搜索联想功能
?
    排序算法改进
?
    全站整合搜索
?
    准实时搜索
Lucene 3
?   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: 等到花儿也谢了
定制功能
?
    在某些情况下作为数据库的替代数据源
    ?
        类似淘宝搜索,按多个字段筛选,过滤,排序
    ?
        当前解决方案:使用 sql 从数据库中选取数据
    ?
        问题:数据可能因为业务逻辑的设计而分散在多个不同的
        库,表中,联表查询问题,并发压力问题
    ?
        难点:非典型的复杂的查询条件,如 group by
参考资料
?
    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
更多讨论

    Java?GC? 的问题
   巨大的索引库与频繁更新如何共存
   全站整合搜索,后台技术实现与前台表现设计
   更多

More Related Content

What's hot (7)

Orclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wang
Orclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wangOrclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wang
Orclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wang
maclean liu
?
自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)
自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)
自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)
OpenFoundry
?
Oracle管理藝術第1章 在Linux作業體統安裝Oracle 11g
Oracle管理藝術第1章 在Linux作業體統安裝Oracle 11gOracle管理藝術第1章 在Linux作業體統安裝Oracle 11g
Oracle管理藝術第1章 在Linux作業體統安裝Oracle 11g
Chien Chung Shen
?
Oracle 索引介紹
Oracle 索引介紹Oracle 索引介紹
Oracle 索引介紹
Chien Chung Shen
?
Oracle试题Exam Adminv1.1
Oracle试题Exam Adminv1.1Oracle试题Exam Adminv1.1
Oracle试题Exam Adminv1.1
Zianed Hou
?
PostgreSQL 9 1 新特性
PostgreSQL 9 1 新特性PostgreSQL 9 1 新特性
PostgreSQL 9 1 新特性
March Liu
?
Orclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wang
Orclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wangOrclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wang
Orclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wang
maclean liu
?
自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)
自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)
自由软体铸造场冲20111023冲厂耻产惫别谤蝉颈辞苍版本控制系统之操作冲曾义峰(补苍迟)
OpenFoundry
?
Oracle管理藝術第1章 在Linux作業體統安裝Oracle 11g
Oracle管理藝術第1章 在Linux作業體統安裝Oracle 11gOracle管理藝術第1章 在Linux作業體統安裝Oracle 11g
Oracle管理藝術第1章 在Linux作業體統安裝Oracle 11g
Chien Chung Shen
?
Oracle试题Exam Adminv1.1
Oracle试题Exam Adminv1.1Oracle试题Exam Adminv1.1
Oracle试题Exam Adminv1.1
Zianed Hou
?
PostgreSQL 9 1 新特性
PostgreSQL 9 1 新特性PostgreSQL 9 1 新特性
PostgreSQL 9 1 新特性
March Liu
?

Similar to 基于尝耻肠别苍别的站内搜索 Beta (20)

数据库持续集成
数据库持续集成数据库持续集成
数据库持续集成
wait4friend
?
从运维系统的开发谈安全架构设计
从运维系统的开发谈安全架构设计从运维系统的开发谈安全架构设计
从运维系统的开发谈安全架构设计
mysqlops
?
Java@taobao
Java@taobaoJava@taobao
Java@taobao
vanadies10
?
Times Ten Training
Times Ten TrainingTimes Ten Training
Times Ten Training
Li Chen
?
开源应用日志收集系统
开源应用日志收集系统开源应用日志收集系统
开源应用日志收集系统
klandor
?
深入研究 Windows 系統服務 效能調校與故障排除
深入研究 Windows 系統服務    效能調校與故障排除深入研究 Windows 系統服務    效能調校與故障排除
深入研究 Windows 系統服務 效能調校與故障排除
5045033
?
尝耻肠别苍别实践
尝耻肠别苍别实践尝耻肠别苍别实践
尝耻肠别苍别实践
晓锋 陈
?
Ocean base海量结构化数据存储系统 hadoop in china
Ocean base海量结构化数据存储系统 hadoop in chinaOcean base海量结构化数据存储系统 hadoop in china
Ocean base海量结构化数据存储系统 hadoop in china
knuthocean
?
Subversion
SubversionSubversion
Subversion
i7Xh
?
奥别产请求异步处理和海量数据即时分析在淘宝开放平台的实践
奥别产请求异步处理和海量数据即时分析在淘宝开放平台的实践奥别产请求异步处理和海量数据即时分析在淘宝开放平台的实践
奥别产请求异步处理和海量数据即时分析在淘宝开放平台的实践
mysqlops
?
Software Engineer Talk
Software Engineer TalkSoftware Engineer Talk
Software Engineer Talk
Larry Cai
?
高性能队列贵辩耻别耻别的设计和使用实践
高性能队列贵辩耻别耻别的设计和使用实践高性能队列贵辩耻别耻别的设计和使用实践
高性能队列贵辩耻别耻别的设计和使用实践
孙立
?
鹰眼下的淘宝_EagleEye with Taobao
鹰眼下的淘宝_EagleEye with Taobao鹰眼下的淘宝_EagleEye with Taobao
鹰眼下的淘宝_EagleEye with Taobao
terryice
?
基于厂测尘蹿辞苍测框架下的快速公司级应用开发
基于厂测尘蹿辞苍测框架下的快速公司级应用开发基于厂测尘蹿辞苍测框架下的快速公司级应用开发
基于厂测尘蹿辞苍测框架下的快速公司级应用开发
mysqlops
?
Java 的開放原碼全文搜尋技術 - Lucene
Java 的開放原碼全文搜尋技術 - LuceneJava 的開放原碼全文搜尋技術 - Lucene
Java 的開放原碼全文搜尋技術 - Lucene
建興 王
?
1~60
1~601~60
1~60
s13993010
?
Kubernetes project update and how to contribute
Kubernetes project update and how to contributeKubernetes project update and how to contribute
Kubernetes project update and how to contribute
inwin stack
?
数据库持续集成
数据库持续集成数据库持续集成
数据库持续集成
wait4friend
?
从运维系统的开发谈安全架构设计
从运维系统的开发谈安全架构设计从运维系统的开发谈安全架构设计
从运维系统的开发谈安全架构设计
mysqlops
?
Times Ten Training
Times Ten TrainingTimes Ten Training
Times Ten Training
Li Chen
?
开源应用日志收集系统
开源应用日志收集系统开源应用日志收集系统
开源应用日志收集系统
klandor
?
深入研究 Windows 系統服務 效能調校與故障排除
深入研究 Windows 系統服務    效能調校與故障排除深入研究 Windows 系統服務    效能調校與故障排除
深入研究 Windows 系統服務 效能調校與故障排除
5045033
?
尝耻肠别苍别实践
尝耻肠别苍别实践尝耻肠别苍别实践
尝耻肠别苍别实践
晓锋 陈
?
Ocean base海量结构化数据存储系统 hadoop in china
Ocean base海量结构化数据存储系统 hadoop in chinaOcean base海量结构化数据存储系统 hadoop in china
Ocean base海量结构化数据存储系统 hadoop in china
knuthocean
?
Subversion
SubversionSubversion
Subversion
i7Xh
?
奥别产请求异步处理和海量数据即时分析在淘宝开放平台的实践
奥别产请求异步处理和海量数据即时分析在淘宝开放平台的实践奥别产请求异步处理和海量数据即时分析在淘宝开放平台的实践
奥别产请求异步处理和海量数据即时分析在淘宝开放平台的实践
mysqlops
?
Software Engineer Talk
Software Engineer TalkSoftware Engineer Talk
Software Engineer Talk
Larry Cai
?
高性能队列贵辩耻别耻别的设计和使用实践
高性能队列贵辩耻别耻别的设计和使用实践高性能队列贵辩耻别耻别的设计和使用实践
高性能队列贵辩耻别耻别的设计和使用实践
孙立
?
鹰眼下的淘宝_EagleEye with Taobao
鹰眼下的淘宝_EagleEye with Taobao鹰眼下的淘宝_EagleEye with Taobao
鹰眼下的淘宝_EagleEye with Taobao
terryice
?
基于厂测尘蹿辞苍测框架下的快速公司级应用开发
基于厂测尘蹿辞苍测框架下的快速公司级应用开发基于厂测尘蹿辞苍测框架下的快速公司级应用开发
基于厂测尘蹿辞苍测框架下的快速公司级应用开发
mysqlops
?
Java 的開放原碼全文搜尋技術 - Lucene
Java 的開放原碼全文搜尋技術 - LuceneJava 的開放原碼全文搜尋技術 - Lucene
Java 的開放原碼全文搜尋技術 - Lucene
建興 王
?
Kubernetes project update and how to contribute
Kubernetes project update and how to contributeKubernetes project update and how to contribute
Kubernetes project update and how to contribute
inwin stack
?

More from zhu02 (20)

Beta Mranti
Beta MrantiBeta Mranti
Beta Mranti
zhu02
?
Sae Technique Brief
Sae Technique BriefSae Technique Brief
Sae Technique Brief
zhu02
?
6 When Travel Meets Net David
6 When Travel Meets Net David6 When Travel Meets Net David
6 When Travel Meets Net David
zhu02
?
8 浜у搧璁捐涓殑浠峰艰 Dm
8 浜у搧璁捐涓殑浠峰艰 Dm8 浜у搧璁捐涓殑浠峰艰 Dm
8 浜у搧璁捐涓殑浠峰艰 Dm
zhu02
?
Music Recommender Systems
Music Recommender SystemsMusic Recommender Systems
Music Recommender Systems
zhu02
?
从搜索到发现
从搜索到发现从搜索到发现
从搜索到发现
zhu02
?
聆听 声音艺术的政治学实践
聆听 声音艺术的政治学实践聆听 声音艺术的政治学实践
聆听 声音艺术的政治学实践
zhu02
?
花旦介绍
花旦介绍花旦介绍
花旦介绍
zhu02
?
叠别迟补肠补尘辫4.选秀
叠别迟补肠补尘辫4.选秀叠别迟补肠补尘辫4.选秀
叠别迟补肠补尘辫4.选秀
zhu02
?
用漫画做环保:胖兔子粥粥个人讲演2绿帽子
用漫画做环保:胖兔子粥粥个人讲演2绿帽子用漫画做环保:胖兔子粥粥个人讲演2绿帽子
用漫画做环保:胖兔子粥粥个人讲演2绿帽子
zhu02
?
Beta Huoju 090823
Beta Huoju 090823Beta Huoju 090823
Beta Huoju 090823
zhu02
?
Youth Volunteer Movement
Youth Volunteer MovementYouth Volunteer Movement
Youth Volunteer Movement
zhu02
?
诗人们都在干嘛
诗人们都在干嘛诗人们都在干嘛
诗人们都在干嘛
zhu02
?
叠别迟补肠补尘辫.姬十叁.2009.8.9
叠别迟补肠补尘辫.姬十叁.2009.8.9叠别迟补肠补尘辫.姬十叁.2009.8.9
叠别迟补肠补尘辫.姬十叁.2009.8.9
zhu02
?
奇遇花园是这个城市的咖啡馆
奇遇花园是这个城市的咖啡馆奇遇花园是这个城市的咖啡馆
奇遇花园是这个城市的咖啡馆
zhu02
?
麦兜四格
麦兜四格麦兜四格
麦兜四格
zhu02
?
胡泳《有关罢飞颈迟迟别谤的疑问》
胡泳《有关罢飞颈迟迟别谤的疑问》胡泳《有关罢飞颈迟迟别谤的疑问》
胡泳《有关罢飞颈迟迟别谤的疑问》
zhu02
?
纪录片创作走向0712
纪录片创作走向0712纪录片创作走向0712
纪录片创作走向0712
zhu02
?
科幻电影引领3 D时代
科幻电影引领3 D时代科幻电影引领3 D时代
科幻电影引领3 D时代
zhu02
?
Beta Mranti
Beta MrantiBeta Mranti
Beta Mranti
zhu02
?
Sae Technique Brief
Sae Technique BriefSae Technique Brief
Sae Technique Brief
zhu02
?
6 When Travel Meets Net David
6 When Travel Meets Net David6 When Travel Meets Net David
6 When Travel Meets Net David
zhu02
?
8 浜у搧璁捐涓殑浠峰艰 Dm
8 浜у搧璁捐涓殑浠峰艰 Dm8 浜у搧璁捐涓殑浠峰艰 Dm
8 浜у搧璁捐涓殑浠峰艰 Dm
zhu02
?
Music Recommender Systems
Music Recommender SystemsMusic Recommender Systems
Music Recommender Systems
zhu02
?
从搜索到发现
从搜索到发现从搜索到发现
从搜索到发现
zhu02
?
聆听 声音艺术的政治学实践
聆听 声音艺术的政治学实践聆听 声音艺术的政治学实践
聆听 声音艺术的政治学实践
zhu02
?
花旦介绍
花旦介绍花旦介绍
花旦介绍
zhu02
?
叠别迟补肠补尘辫4.选秀
叠别迟补肠补尘辫4.选秀叠别迟补肠补尘辫4.选秀
叠别迟补肠补尘辫4.选秀
zhu02
?
用漫画做环保:胖兔子粥粥个人讲演2绿帽子
用漫画做环保:胖兔子粥粥个人讲演2绿帽子用漫画做环保:胖兔子粥粥个人讲演2绿帽子
用漫画做环保:胖兔子粥粥个人讲演2绿帽子
zhu02
?
Beta Huoju 090823
Beta Huoju 090823Beta Huoju 090823
Beta Huoju 090823
zhu02
?
Youth Volunteer Movement
Youth Volunteer MovementYouth Volunteer Movement
Youth Volunteer Movement
zhu02
?
诗人们都在干嘛
诗人们都在干嘛诗人们都在干嘛
诗人们都在干嘛
zhu02
?
叠别迟补肠补尘辫.姬十叁.2009.8.9
叠别迟补肠补尘辫.姬十叁.2009.8.9叠别迟补肠补尘辫.姬十叁.2009.8.9
叠别迟补肠补尘辫.姬十叁.2009.8.9
zhu02
?
奇遇花园是这个城市的咖啡馆
奇遇花园是这个城市的咖啡馆奇遇花园是这个城市的咖啡馆
奇遇花园是这个城市的咖啡馆
zhu02
?
麦兜四格
麦兜四格麦兜四格
麦兜四格
zhu02
?
胡泳《有关罢飞颈迟迟别谤的疑问》
胡泳《有关罢飞颈迟迟别谤的疑问》胡泳《有关罢飞颈迟迟别谤的疑问》
胡泳《有关罢飞颈迟迟别谤的疑问》
zhu02
?
纪录片创作走向0712
纪录片创作走向0712纪录片创作走向0712
纪录片创作走向0712
zhu02
?
科幻电影引领3 D时代
科幻电影引领3 D时代科幻电影引领3 D时代
科幻电影引领3 D时代
zhu02
?

基于尝耻肠别苍别的站内搜索 Beta

  • 1. 基于 lucene 的站内搜索实战 Beta 技术沙龙 http://club.blogbeta.com 官方 twitter : @betasalon tangfulin <tangfulin@gmail.com> www.imobile.com.cn 2009.07.26
  • 2. 目录  对于手机之家  过去:手机之家搜索 V1.0  现在:手机之家搜索 V1.5  需求背景  目标  进度  设计  实现  测试  上线,运维  经验分享  将来:手机之家搜索 V2.0
  • 3. 目录  对于手机之家  过去:手机之家搜索 V1.0  现在:手机之家搜索 V1.5  需求背景  目标  进度  设计  实现  测试  上线,运维  经验分享  将来:手机之家搜索 V2.0
  • 6. 目录  对于手机之家  过去:手机之家搜索 V1.0  现在:手机之家搜索 V1.5  需求背景  目标  进度  设计  实现  测试  上线,运维  经验分享  将来:手机之家搜索 V2.0
  • 7. 手机之家的搜索 V1.0(1/3)  产物大全搜索  新闻 CMS? 搜索  论坛搜索(默认只搜索标题)  论坛帖子及回复搜索  手机铃声,主题,电子书,软件搜索  二手交易搜索  其它版块的搜索
  • 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 年 4 月 ? 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 更新手机之家内容的周期为 30 分钟左右 ? V1.0 索引更新周期为 10 - 15 分钟左右 ? V1.5 预期更新周期为 3 分钟,实际为 1-5 分钟
  • 14. 需求背景 (3/3) ? 搜索大索引( V1.5 ) ? 3300+ 万条记录的一个库, xml 原始文件 14G ? V1.0 索引文件为 13 G ,无法快速更新 ? V1.5 索引文件为 3.9G (还是无法快速更新?) ? V1.5 完整重建一次: 140 分钟
  • 15. 目录  对于手机之家  过去:手机之家搜索 V1.0  现在:手机之家搜索 V1.5  需求背景  目标  进度  设计  实现  测试  上线,运维  经验分享  将来:手机之家搜索 V2.0
  • 16. 目标 ? 及时更新( 3 分钟) ? 快速重建( < 2 小时) ? 可配置(拥抱需求变化) ? 可监控(运维友好) ? SLA :永远可写,永远可读,异常的时候唯一的表现是 更新延迟 ? 高性能,能承受较大的流量,并发压力
  • 17. 目录  对于手机之家  过去:手机之家搜索 V1.0  现在:手机之家搜索 V1.5  需求背景  目标  进度  设计  实现  测试  上线,运维  经验分享  将来:手机之家搜索 V2.0
  • 18. 进度 ? 2009 年 4 月 1 号 search 2.0 init ? 4 月 12 号,修改版本号为 1.5 ? 6 月 1 号, search 1.5 在线上试运行 ? 6 月 22 号,正式替换原来的搜索进程
  • 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) IndexRebuilder 搜索管理后台 发出开始重建索引命令 IndexReceiver cron 发送重建数据 Rebuild xml data 端口 1986 Update xml data IndexUpdater DAL 数据更新 配置文件 同步通知搜索 Searcher 搜索客户端调用 Searcher 的 API 端口 1985
  • 30. 实现 (2/8)IndexReceiver IndexRebuilder 搜索管理后台 IndexReceiver 发出开始重建索引命令 cron 发送重建数据 Rebuild xml data 端口 1986 Update xml data IndexUpdater DAL 数据更新 配置文件 同步通知搜索 Searcher 搜索客户端调用 Searcher 的 API 端口 1985
  • 31. 实现 (2/8)IndexReceiver ? By Java , Daemon 程序 ? 监听端口,使用 SCGI 通讯协议 ? 使用 Monkey 为底层 NIO 处理框架 ? 接收客户端 post 过来的数据,并写入对应的目录 ? Update 和 rebuild 共用 ? 为了保证原子性,先写入 .0.***.xml ,写入完成后,再 rename ? Receiver 只负责写入, updater 和 rebuilder 稍后负责删除(备份) ? 对外提供服务,所以尽可能简单,单独进程
  • 32. 实现 (3/8)IndexUpdater IndexRebuilder 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 Rebuild xml data 端口 1986 Update IndexUpdater xml data DAL 数据更新 配置文件 同步通知搜索 Searcher 搜索客户端调用 Searcher 的 API 端口 1985
  • 33. 实现 (3/8)IndexUpdater ? By Java , Daemon 程序 ? 多个索引共用,每个索引起一个线程 ? 可根据需要随时停止或启动单个索引更新的线程 ? AddShutdownHook 退出前 close 所有打开的 IndexWriter ? 功能: ? 更新新数据到当前索引 ? 合并大小库 ? 拷贝当前索引的快照供搜索使用 ? 切换 rebuild 出来的新索引
  • 34. 实现 (4/8)IndexRebuilder IndexRebuilder 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 Rebuild xml data 端口 1986 Update xml data DAL 数据更新 配置文件 同步通知搜索 Searcher 搜索客户端调用 Searcher 的 API 端口 1985
  • 35. 实现 (4/8)IndexRebuilder ? By Java , Daemon 程序 ? 多个索引共用,每个索引一个线程 ? 重建索引时序图: Receiver 接到通 知,停止抄送 updater 数据。 客户端发送开 客户端发送重 客户端发送结 重建过程结束 始重建标识 建索引的数据 束重建标识 Receiver 开始抄送 update 数据到 receiver rebuild-update Updater 接到 Updater 正常 通知,切换索 T0 T1 T2 T3 T4 T5 更新 引。完成后通 updater 知 receiver Rebuilder Rebuilder Rebuilder 处理完 t0 开始工作 处理完重 到 当前的更新数据, rebuilder 建数据 通知 updater ,然后 自己退出 开始重建 重建数据 重建完成 时间线 接收完毕
  • 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. 实现 (6/8)Transfer 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 Rebuild xml data 端口 1986 Update xml data DAL 数据更新 配置文件 同步通知搜索 Searcher Transfer 搜索客户端调用 Searcher 的 API 端口 1985
  • 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. 实现 (7/8)Searcher 搜索管理后台 发出开始重建索引命令 cron 发送重建数据 Rebuild xml data 端口 1986 Update xml data DAL 数据更新 配置文件 同步通知搜索 Searcher 搜索客户端调用 Searcher 的 API 端口 1985
  • 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. 性能简单测试结果 ? Apache?bench ? ?n?1000??c?10?? ( 99%????545ms?????100%??32838ms ) ? ?n?2000??c?20?? ( 90%???1171ms????99%???4106ms ) ? 库大小: 4.1G 条目数: 3300+w 更新周期: 1 分钟 ? 总请求 3000 ,慢查询 ( 耗时大于 1 秒 ) 比例 4% ? 搜索词:手机之家论坛首页的板块名,随机 ? 最长: 37s ? >?10s?:?22? (索引切换, gc ) ? 2s?10s?:?38 ? 1s?2s?:?62
  • 44. 性能对比测试结果 (1/6) ? Apache?bench ? 库大小: 4.1G ,条目数: 3300+w ,更新周期: 1 分钟 ? 搜索词:手机之家论坛板块名随机 ? 对比条件 ? 停止更新与正常更新 ? 分配索引 1 倍大小的内存与 2 倍大小的内存 ? 并发 10 个与 20 个 ? Document?Length:?????1529?bytes ? Total?transferred:???????3447737?bytes?(1722053?bytes) ? HTML?transferred:????3085737?bytes?(1541053?bytes)
  • 45. 性能对比测试结果 (2/6) Time taken for tests 停止更新 正常更新 分配索引大小1倍内存 ab -n 2000 -c 20 21.85 64.17 分配索引大小1倍内存 ab -n 1000 -c 10 13.1 11.93 分配索引大小2倍内存 ab -n 2000 -c 20 22.8 22.89 分配索引大小2倍内存 ab -n 1000 -c 10 10.37 10.74 备注:单位为秒
  • 46. 性能对比测试结果 (3/6) Requests per second 停止更新 正常更新 分配索引大小1倍内存 ab -n 2000 -c 20 91.52 31.17 分配索引大小1倍内存 ab -n 1000 -c 10 76.33 83.83 分配索引大小2倍内存 ab -n 2000 -c 20 87.71 87.39 分配索引大小2倍内存 ab -n 1000 -c 10 96.45 93.13
  • 47. 性能对比测试结果 (4/6) Time per request 停止更新 正常更新 218.531 641.674 分配索引大小1倍内存 ab -n 2000 -c 20 10.927 32.084 131.015 119.288 分配索引大小1倍内存 ab -n 1000 -c 10 13.102 11.929 228.012 228.870 分配索引大小2倍内存 ab -n 2000 -c 20 11.401 11.444 103.676 107.375 分配索引大小2倍内存 ab -n 1000 -c 10 10.368 10.738 备注: [ms] (mean) (mean, across all concurrent requests)
  • 48. 性能对比测试结果 (5/6) Transfer rate 停止更新 正常更新 分配索引大小1倍内存 ab -n 2000 -c 20 154.06 52.47 分配索引大小1倍内存 ab -n 1000 -c 10 128.46 140.98 分配索引大小2倍内存 ab -n 2000 -c 20 147.63 146.82 分配索引大小2倍内存 ab -n 1000 -c 10 162.07 156.39 备注: (Kbytes/sec)
  • 49. 性能对比测试结果 (6/6) 耗时比例 停止更新 正常更新 50% 59 50% 162 95% 905 90% 1403 分配索引大小1倍内存 ab -n 2000 -c 20 100% 1525 98% 5738 50% 34 50% 24 99% 978 98% 750 分配索引大小1倍内存 ab -n 1000 -c 10 100% 1420 100% 3600 50% 61 50% 41 95% 906 95% 988 分配索引大小2倍内存 ab -n 2000 -c 20 99% 1519 99% 1678 50% 28 50% 27 99% 744 99% 698 分配索引大小2倍内存 ab -n 1000 -c 10 100% 905 100% 764 备注:百分比 毫秒
  • 50. 目录  对于手机之家  过去:手机之家搜索 V1.0  现在:手机之家搜索 V1.5  需求背景  目标  进度  设计  实现  测试  上线,运维  经验分享  将来:手机之家搜索 V2.0
  • 51. 部署上线 ? 运行概况 ? 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 条 / 分钟
  • 52. 生产环境运行观察 ? Slow?search? 比例: >1s?1.x%;?>2s?0.2% ? 机器负载 : 49(search):?1~3;?50(update):?<1 ? 内存消耗: search:??Xms4096M??Xmx4096M ? Cpu 消耗 :多核之间平均比较分配 ? 索引平均更新速度: ~1 分钟 ? 索引延迟率(因各种原因导致延迟更新的比例)
  • 53. 目录  对于手机之家  过去:手机之家搜索 V1.0  现在:手机之家搜索 V1.5  需求背景  目标  进度  设计  实现  测试  上线,运维  经验分享  将来:手机之家搜索 V2.0
  • 54. 开发中的一些收获 (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 链接替代真实的 大文件拷贝动作
  • 55. 开发中的一些收获 (2/5) ? Kill? 的问题 ? Never?kill?smart?frog,?don't?kill??9 ? Java?use?Runtime.getRuntime().addShutdownHook??to?do?the?cleaning? things ? Lucene?IndexWriter?need?close! ? server? 程序,都应该考虑信号捕捉和处理的问题( java? 程序容易忽 略这个问题)
  • 56. 开发中的一些收获 (3/5) ? 更新太频繁导致的磁盘 IO 问题 – 同一台机器目录之间同步:没有问题 – 一拖二,一拖三 ? 暂时解决 – 建索引的机器不提供搜索服务 – rsync 限速
  • 57. 开发中的一些收获 (4/5) ? GC? 引起的服务暂停 ? 多个索引共用 Search 进程 ? 每个索引维持了多个 searcher ? 索引更新太过频繁: 30 秒 ? 暂时解决 ? 纵向拆分:将两个最大的库拆分到单独的进程 ? 减少 searcher 个数到 2? 个 ? 谨慎的选择 gc 的类型,并调整 gc 的参数 ? G1 改进不明显,不稳定
  • 58. 开发中的一些收获 (5/5) ? Java?server? 程序的 trouble?shooting ? 性能问题: jprofile ? 内存问题: jmx? + jconsole ? 线程问题: Thread.currentThread().setName("diffDetect?"?+? indexId);? ? 详细的 log : log4j ? 常用的脚本: logslowsearch.sh ? 开发调试阶段:方便的重新编译并重启脚本 ? 线上服务阶段:完善的监控及报警机制
  • 59. 目录  对于手机之家  过去:手机之家搜索 V1.0  现在:手机之家搜索 V1.5  需求背景  目标  进度  设计  实现  测试  上线,运维  经验分享  将来:手机之家搜索 V2.0
  • 60. 持续改进 ? 配置文件改动检测,自动重新加载 ? 更智能的处理索引字段变更 ? 分词算法改进 ? 搜索关键字数据挖掘(搜索新词自动发现) ? 搜索建议,搜索联想功能 ? 排序算法改进 ? 全站整合搜索 ? 准实时搜索
  • 61. Lucene 3 ? 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: 等到花儿也谢了
  • 62. 定制功能 ? 在某些情况下作为数据库的替代数据源 ? 类似淘宝搜索,按多个字段筛选,过滤,排序 ? 当前解决方案:使用 sql 从数据库中选取数据 ? 问题:数据可能因为业务逻辑的设计而分散在多个不同的 库,表中,联表查询问题,并发压力问题 ? 难点:非典型的复杂的查询条件,如 group by
  • 63. 参考资料 ? 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
  • 64. 对于我们 ? 对于 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
  • 65. 更多讨论  Java?GC? 的问题  巨大的索引库与频繁更新如何共存  全站整合搜索,后台技术实现与前台表现设计  更多