OSChina是如何处理索引更新问题的

一般使用 Lucene 来做全文搜索时,都会碰到这样一个问题,什么时候创建、更新或者删除索引。

假设是发帖子吧,如果一发贴就即时写入索引,好处是索引及时,但这会引起索引库被锁的问题,因为同一个时间可能很多人都在发帖,更新和删除都是同样的问题存在。

还有另外一个方法是后台定时将新增的帖子写入索引库,这种可以避免索引库被锁的问题,不过刚发的帖子就没法被索引到(这个不是大问题,一般都可以接受),但是对一些帖子的修改和删除,处理起来就比较麻烦,你不知道哪些帖子被改了,或者被删了。

OSChina 现在的做法是引入一个 LuceneTask 类,代表要执行的一次索引任务,这个任务可以是添加、修改或者删除,每次新增帖子、修改帖子或者删除帖子时,只是对应的往数据库的一个表里写入一条 LuceneTask 数据即可。而后台通过 crontab 每隔一分钟从 LuceneTask 表中检索出待处理的索引任务记录,处理完毕后将该记录的状态改为已完成。

LuceneTask 类的代码如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package net.oschina.search;
 
import java.util.Date;
 
import my.db.QueryHelper;
import my.search.SearchEnabled;
import net.oschina.beans.Article;
import net.oschina.beans.Blog;
import net.oschina.beans.News;
import net.oschina.beans.Pojo;
import net.oschina.beans.Project;
 
/**
  * Lucene索引更新任务
  * @author Winter Lau
  * @date 2010-1-4 下午04:57:47
  */
public class LuceneTask extends Pojo {
     
     public final static transient byte OPT_ADD      = 0x01 ;
     public final static transient byte OPT_UPDATE   = 0x02 ;
     public final static transient byte OPT_DELETE   = 0x04 ;
     
     /**
      * 返回对应的对象资料
      * @return
      */
     public SearchEnabled object(){
         switch (obj_type) {
         case TYPE_PROJECT:
             return (Project)Project.INSTANCE.Get(obj_id);
         case TYPE_NEWS:
             return (News)News.INSTANCE.Get(obj_id);
         case TYPE_THREAD:
             return net.oschina.beans.Thread.Read(obj_id);
         case TYPE_ARTICLE:
             return (Article)Article.INSTANCE.Get(obj_id);
         case TYPE_BLOG:
             return (Blog)Blog.INSTANCE.Get(obj_id);
         }
         return null ;
     }
     
     public void afterBuild(){
         String sql = "UPDATE osc_lucene_tasks SET status=1,handle_time=NOW() WHERE id=?" ;
         QueryHelper.update(sql, getId());
     }
     
     public static void add( long obj_id, byte obj_type) {
         new LuceneTask(obj_id, obj_type, OPT_ADD).Save();
     }
 
     public static void update( long obj_id, byte obj_type) {
         new LuceneTask(obj_id, obj_type, OPT_UPDATE).Save();
     }
 
     public static void delete( long obj_id, byte obj_type) {
         new LuceneTask(obj_id, obj_type, OPT_DELETE).Save();
     }
     
     public LuceneTask() {
     }
 
     public LuceneTask( long obj_id, byte obj_type, byte opt) {
         this .obj_id = obj_id;
         this .obj_type = obj_type;
         this .opt = opt;
         this .status = 0 ;
     }
 
     private long obj_id;
     private byte obj_type;
     private byte opt;
     private byte status;
     private Date create_time;
     private Date handle_time;
     
     public long getObj_id() {
         return obj_id;
     }
     public void setObj_id( long obj_id) {
         this .obj_id = obj_id;
     }
     public byte getObj_type() {
         return obj_type;
     }
     public void setObj_type( byte obj_type) {
         this .obj_type = obj_type;
     }
     public byte getOpt() {
         return opt;
     }
     public void setOpt( byte opt) {
         this .opt = opt;
     }
     public byte getStatus() {
         return status;
     }
     public void setStatus( byte status) {
         this .status = status;
     }
     public Date getCreate_time() {
         return create_time;
     }
     public void setCreate_time(Date create_time) {
         this .create_time = create_time;
     }
     public Date getHandle_time() {
         return handle_time;
     }
     public void setHandle_time(Date handle_time) {
         this .handle_time = handle_time;
     }
     
}

其中 obj_id 代表帖子的编号,obj_type 代表帖子的类型,可以是帖子,可以是新闻,也可以是软件。

这个结构其实挺适合 Lucene 实现索引的各类项目,所以贴出来分享一下。

红薯 红薯
发帖于 5年前
14回/3998阅

按默认排序  显示最新评论  共有14个评论 (最后回答: 1年前)

  • 0
  • chen辉
    没有完整源码,小白表示看的云里雾里!
    评论(0)引用此评论| 举报 (2013-11-01 14:00)
    0
  • 梁某某
    红薯您好,我现在一个项目需要用到lucene,我想在请教您一下,  lucene更新索引的效率到底如何,比如:我目前数据库有30万,数据,估计从数据库查询取数据到创建索引完成会要多久呢?不考虑服务器性能方面的问题!
    评论(0)引用此评论| 举报 (2013-04-27 21:59)
    0
  • 好像还有个机制就是增加或者更新的索引先写到内存里,每隔一定的时候与硬盘中索引合并

    这样可以做到及时索引

    但是如果出现down机了 内存中的索引就over了

    评论(0)引用此评论| 举报 (2012-10-28 21:04)
    0
  • 林毅文
    真的顶一下。
    评论(0)引用此评论| 举报 (2012-10-23 16:45)
    0
  • Mr_Idk
    关注... 
    评论(0)引用此评论| 举报 (2012-09-07 20:40)
    0
  • 颜磊
    这个想法,见过,哈哈
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值