SlideShare a Scribd company logo
1 of 65
Download to read offline
基于 lucene 的站内搜索实战
  tangfulin <tangfulin@gmail.com>
        www.imobile.com.cn
     2009.07.26 @beta 技术沙龙
目录
   关于手机之家
   过去:手机之家搜索 V1.0
   现在:手机之家搜索 V1.5
       需求背景
       目标
       进度
       设计
       实现
       测试
       上线,运维
       经验分享
   将来:手机之家搜索 V2.0
目录
   关于手机之家
   过去:手机之家搜索 V1.0
   现在:手机之家搜索 V1.5
       需求背景
       目标
       进度
       设计
       实现
       测试
       上线,运维
       经验分享
   将来:手机之家搜索 V2.0
关于手机之家

手机之家是一个旨在提供全方位的手机相关服务的资讯类网站。在 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

Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
yiditushe
 
PostgreSQL 9 1 新特性
PostgreSQL 9 1 新特性PostgreSQL 9 1 新特性
PostgreSQL 9 1 新特性
March Liu
 
配置Oracle 10g 双向流复制
配置Oracle 10g 双向流复制配置Oracle 10g 双向流复制
配置Oracle 10g 双向流复制
maclean liu
 
I pv6電子郵件系統講習 0623_v2
I pv6電子郵件系統講習 0623_v2I pv6電子郵件系統講習 0623_v2
I pv6電子郵件系統講習 0623_v2
宏義 張
 

What's hot (11)

自由軟體鑄造場_20111023_Subversion版本控制系統之操作_曾義峰(ant)
自由軟體鑄造場_20111023_Subversion版本控制系統之操作_曾義峰(ant)自由軟體鑄造場_20111023_Subversion版本控制系統之操作_曾義峰(ant)
自由軟體鑄造場_20111023_Subversion版本控制系統之操作_曾義峰(ant)
 
Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿Itpub电子杂志第四期第二稿
Itpub电子杂志第四期第二稿
 
Oracle管理藝術第1章 在Linux作業體統安裝Oracle 11g
Oracle管理藝術第1章 在Linux作業體統安裝Oracle 11gOracle管理藝術第1章 在Linux作業體統安裝Oracle 11g
Oracle管理藝術第1章 在Linux作業體統安裝Oracle 11g
 
Cdc@ganji.com
Cdc@ganji.comCdc@ganji.com
Cdc@ganji.com
 
PostgreSQL 9 1 新特性
PostgreSQL 9 1 新特性PostgreSQL 9 1 新特性
PostgreSQL 9 1 新特性
 
Oda安装 恢复步骤
Oda安装 恢复步骤Oda安装 恢复步骤
Oda安装 恢复步骤
 
Oracle 索引介紹
Oracle 索引介紹Oracle 索引介紹
Oracle 索引介紹
 
【诗檀软件 郭兆伟-技术报告】跨国企业级Oracle数据库备份策略
【诗檀软件 郭兆伟-技术报告】跨国企业级Oracle数据库备份策略【诗檀软件 郭兆伟-技术报告】跨国企业级Oracle数据库备份策略
【诗檀软件 郭兆伟-技术报告】跨国企业级Oracle数据库备份策略
 
配置Oracle 10g 双向流复制
配置Oracle 10g 双向流复制配置Oracle 10g 双向流复制
配置Oracle 10g 双向流复制
 
I pv6電子郵件系統講習 0623_v2
I pv6電子郵件系統講習 0623_v2I pv6電子郵件系統講習 0623_v2
I pv6電子郵件系統講習 0623_v2
 
dbdao.com 汪伟华 my-sql-replication复制高可用配置方案
dbdao.com 汪伟华 my-sql-replication复制高可用配置方案dbdao.com 汪伟华 my-sql-replication复制高可用配置方案
dbdao.com 汪伟华 my-sql-replication复制高可用配置方案
 

Viewers also liked

系统邮件实战技巧
系统邮件实战技巧系统邮件实战技巧
系统邮件实战技巧
samon127
 
The Rules of Scalable database
The Rules of Scalable databaseThe Rules of Scalable database
The Rules of Scalable database
Dahui Feng
 
内部MySQL培训.1.基础技能
内部MySQL培训.1.基础技能内部MySQL培训.1.基础技能
内部MySQL培训.1.基础技能
Lixun Peng
 
MySQL新技术探索与实践
MySQL新技术探索与实践MySQL新技术探索与实践
MySQL新技术探索与实践
Lixun Peng
 

Viewers also liked (20)

运维超级管理工具 Super agent
运维超级管理工具 Super agent运维超级管理工具 Super agent
运维超级管理工具 Super agent
 
系统邮件实战技巧
系统邮件实战技巧系统邮件实战技巧
系统邮件实战技巧
 
人大2010新生住宿指南
人大2010新生住宿指南人大2010新生住宿指南
人大2010新生住宿指南
 
腾讯即时聊天IM1.4亿在线背后的故事
腾讯即时聊天IM1.4亿在线背后的故事腾讯即时聊天IM1.4亿在线背后的故事
腾讯即时聊天IM1.4亿在线背后的故事
 
MySQL数据库生产环境维护
MySQL数据库生产环境维护MySQL数据库生产环境维护
MySQL数据库生产环境维护
 
数据库部门介绍
数据库部门介绍 数据库部门介绍
数据库部门介绍
 
The Rules of Scalable database
The Rules of Scalable databaseThe Rules of Scalable database
The Rules of Scalable database
 
Go Lang
Go LangGo Lang
Go Lang
 
Oracle Security 101
Oracle Security 101Oracle Security 101
Oracle Security 101
 
Go
GoGo
Go
 
集群运维管理平台
集群运维管理平台集群运维管理平台
集群运维管理平台
 
Optimzing mysql
Optimzing mysqlOptimzing mysql
Optimzing mysql
 
内部MySQL培训.1.基础技能
内部MySQL培训.1.基础技能内部MySQL培训.1.基础技能
内部MySQL培训.1.基础技能
 
淘宝主备数据库自动切换
淘宝主备数据库自动切换淘宝主备数据库自动切换
淘宝主备数据库自动切换
 
Wind Computing
Wind ComputingWind Computing
Wind Computing
 
MySQL新技术探索与实践
MySQL新技术探索与实践MySQL新技术探索与实践
MySQL新技术探索与实践
 
内部MySQL培训.3.基本原理
内部MySQL培训.3.基本原理内部MySQL培训.3.基本原理
内部MySQL培训.3.基本原理
 
DBA新人的述职报告
DBA新人的述职报告DBA新人的述职报告
DBA新人的述职报告
 
MySQL AIO详解
MySQL AIO详解MySQL AIO详解
MySQL AIO详解
 
My Sql Proxy
My Sql ProxyMy Sql Proxy
My Sql Proxy
 

Similar to 基于Lucene的站内搜索 Beta

数据库持续集成
数据库持续集成数据库持续集成
数据库持续集成
wait4friend
 
Times Ten Training
Times Ten TrainingTimes Ten Training
Times Ten Training
Li Chen
 
深入研究 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
 
網站設計100步
網站設計100步網站設計100步
網站設計100步
evercislide
 
Subversion
SubversionSubversion
Subversion
i7Xh
 
数据库性能诊断的七种武器
数据库性能诊断的七种武器数据库性能诊断的七种武器
数据库性能诊断的七种武器
Leyi (Kamus) Zhang
 
Openstack document for apac v3
Openstack document for apac v3Openstack document for apac v3
Openstack document for apac v3
OpenCity Community
 

Similar to 基于Lucene的站内搜索 Beta (20)

基于Lucene的站内搜索 Beta
基于Lucene的站内搜索 Beta基于Lucene的站内搜索 Beta
基于Lucene的站内搜索 Beta
 
数据库持续集成
数据库持续集成数据库持续集成
数据库持续集成
 
从运维系统的开发谈安全架构设计
从运维系统的开发谈安全架构设计从运维系统的开发谈安全架构设计
从运维系统的开发谈安全架构设计
 
Times Ten Training
Times Ten TrainingTimes Ten Training
Times Ten Training
 
深入研究 Windows 系統服務 效能調校與故障排除
深入研究 Windows 系統服務    效能調校與故障排除深入研究 Windows 系統服務    效能調校與故障排除
深入研究 Windows 系統服務 效能調校與故障排除
 
Java@taobao
Java@taobaoJava@taobao
Java@taobao
 
Ocean base海量结构化数据存储系统 hadoop in china
Ocean base海量结构化数据存储系统 hadoop in chinaOcean base海量结构化数据存储系统 hadoop in china
Ocean base海量结构化数据存储系统 hadoop in china
 
开源应用日志收集系统
开源应用日志收集系统开源应用日志收集系统
开源应用日志收集系统
 
網站設計100步
網站設計100步網站設計100步
網站設計100步
 
Subversion
SubversionSubversion
Subversion
 
Java 的開放原碼全文搜尋技術 - Lucene
Java 的開放原碼全文搜尋技術 - LuceneJava 的開放原碼全文搜尋技術 - Lucene
Java 的開放原碼全文搜尋技術 - Lucene
 
Lucene实践
Lucene实践Lucene实践
Lucene实践
 
Web请求异步处理和海量数据即时分析在淘宝开放平台的实践
Web请求异步处理和海量数据即时分析在淘宝开放平台的实践Web请求异步处理和海量数据即时分析在淘宝开放平台的实践
Web请求异步处理和海量数据即时分析在淘宝开放平台的实践
 
数据库性能诊断的七种武器
数据库性能诊断的七种武器数据库性能诊断的七种武器
数据库性能诊断的七种武器
 
高性能队列Fqueue的设计和使用实践
高性能队列Fqueue的设计和使用实践高性能队列Fqueue的设计和使用实践
高性能队列Fqueue的设计和使用实践
 
鹰眼下的淘宝_EagleEye with Taobao
鹰眼下的淘宝_EagleEye with Taobao鹰眼下的淘宝_EagleEye with Taobao
鹰眼下的淘宝_EagleEye with Taobao
 
Exodus2 大局观
Exodus2 大局观Exodus2 大局观
Exodus2 大局观
 
敦群學院-SharePoint精英計畫-系統開發-Day 3
敦群學院-SharePoint精英計畫-系統開發-Day 3敦群學院-SharePoint精英計畫-系統開發-Day 3
敦群學院-SharePoint精英計畫-系統開發-Day 3
 
1~60
1~601~60
1~60
 
Openstack document for apac v3
Openstack document for apac v3Openstack document for apac v3
Openstack document for apac v3
 

基于Lucene的站内搜索 Beta

  • 1. 基于 lucene 的站内搜索实战 tangfulin <tangfulin@gmail.com> www.imobile.com.cn 2009.07.26 @beta 技术沙龙
  • 2. 目录  关于手机之家  过去:手机之家搜索 V1.0  现在:手机之家搜索 V1.5  需求背景  目标  进度  设计  实现  测试  上线,运维  经验分享  将来:手机之家搜索 V2.0
  • 3. 目录  关于手机之家  过去:手机之家搜索 V1.0  现在:手机之家搜索 V1.5  需求背景  目标  进度  设计  实现  测试  上线,运维  经验分享  将来:手机之家搜索 V2.0
  • 4.
  • 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  的问题  巨大的索引库与频繁更新如何共存  全站整合搜索,后台技术实现与前台表现设计  更多