前面说过,接收indexerRequest的代码在index_worker.go里:

func (engine *Engine) indexerAddDocumentWorker(shard int) {
for {
request := <-engine.indexerAddDocumentChannels[shard] //关键
addInvertedIndex := engine.indexers[shard].AddDocument(request.document, request.dealDocInfoChan) // 向反向索引表(数组)中加入一个文档
// save
if engine.initOptions.UsePersistentStorage {
for k, v := range addInvertedIndex {
engine.persistentStorageIndexDocumentChannels[shard] <- persistentStorageIndexDocumentRequest{
typ: "index",
keyword: k,
keywordIndices: v,
}
}
} atomic.AddUint64(&engine.numTokenIndexAdded,
uint64(len(request.document.Keywords)))
atomic.AddUint64(&engine.numDocumentsIndexed, )
}

持久化的代码:engine/persistent_storage_worker.go

package engine

import (
"bytes"
"encoding/binary"
"encoding/gob"
"github.com/huichen/wukong/core"
"github.com/huichen/wukong/types"
"sync"
"sync/atomic"
) type persistentStorageIndexDocumentRequest struct {
typ string //"info"or"index" // typ=="info"时,以下两个字段有效
docId uint64
docInfo *types.DocInfo // typ=="index"时,以下两个字段有效
keyword string
keywordIndices *types.KeywordIndices
} func (engine *Engine) persistentStorageIndexDocumentWorker(shard int) {
for {
request := <-engine.persistentStorageIndexDocumentChannels[shard]
switch request.typ {
case "info":
// 得到key
b := make([]byte, )
length := binary.PutUvarint(b, request.docId) // 得到value
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
err := enc.Encode(request.docInfo)
if err != nil {
atomic.AddUint64(&engine.numDocumentsStored, )
return
} // 将key-value写入数据库
engine.dbs[shard][getDB(request.typ)].Set(b[:length], buf.Bytes())
atomic.AddUint64(&engine.numDocumentsStored, ) case "index":
// 得到key
b := []byte(request.keyword) // 得到value
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
err := enc.Encode(request.keywordIndices)
if err != nil {
return
} // 将key-value写入数据库
engine.dbs[shard][getDB(request.typ)].Set(b, buf.Bytes())
}
}
} func (engine *Engine) persistentStorageRemoveDocumentWorker(docId uint64, shard int) {
// 得到key
b := make([]byte, )
length := binary.PutUvarint(b, docId) // 从数据库删除该key
engine.dbs[shard][getDB("info")].Delete(b[:length])
} func (engine *Engine) persistentStorageInitWorker(shard int) {
var finish sync.WaitGroup
finish.Add()
// 恢复docInfo
go func() {
defer finish.Add(-)
engine.dbs[shard][getDB("info")].ForEach(func(k, v []byte) error {
key, value := k, v
// 得到docID
docId, _ := binary.Uvarint(key) // 得到data
buf := bytes.NewReader(value)
dec := gob.NewDecoder(buf)
var data types.DocInfo
err := dec.Decode(&data)
if err == nil {
// 添加索引
core.AddDocInfo(shard, docId, &data)
}
return nil
})
}() // 恢复invertedIndex
go func() {
defer finish.Add(-)
engine.dbs[shard][getDB("index")].ForEach(func(k, v []byte) error {
key, value := k, v
// 得到keyword
keyword := string(key) // 得到data
buf := bytes.NewReader(value)
dec := gob.NewDecoder(buf)
var data types.KeywordIndices
err := dec.Decode(&data)
if err == nil {
// 添加索引
core.AddKeywordIndices(shard, keyword, &data)
}
return nil
})
}()
finish.Wait()
engine.persistentStorageInitChannel <- true
}

可以看到,倒排索引存在DB里是丑陋的,直接set(key, value) 其中,key是倒排列表的关键字,而value是doc id list也就是数组。

如果索引比较多,每次去DB set是非常耗时的,尤其针对同一个keyword有doc id插入时!

总之,wukong对于持久化的做法很丑陋!

wukong引擎源码分析之索引——part 2 持久化 直接set(key,docID数组)在kv存储里的更多相关文章

  1. wukong引擎源码分析之索引——part 1 倒排列表本质是有序数组存储

    searcher.IndexDocument(0, types.DocumentIndexData{Content: "此次百度收购将成中国互联网最大并购"}) engine.go ...

  2. wukong引擎源码分析之索引——part 3 文档评分 无非就是将docid对应的fields信息存储起来,为搜索结果rank评分用

    之前的文章分析过,接受索引请求处理的代码在segmenter_worker.go里: func (engine *Engine) segmenterWorker() { for { request : ...

  3. wukong引擎源码分析之搜索——docid有序的数组里二分归并求交集,如果用跳表的话,在插入索引时会更快

    searcher.Search(types.SearchRequest{Text: "百度中国"}) // 查找满足搜索条件的文档,此函数线程安全 func (engine *En ...

  4. Spark源码分析 – 汇总索引

    http://jerryshao.me/categories.html#architecture-ref http://blog.csdn.net/pelick/article/details/172 ...

  5. bleve搜索引擎源码分析之索引——mapping真复杂啊

    接下来看看下面index部分的源码实现: data := struct { Name string Des string }{ Name: "hello world this is bone ...

  6. 转:Irrlicht 0.1引擎源码分析与研究(一)

    目录(?)[-] 主要技术特性 引擎概览 Irrlicht的窗口管理   Irrlicht引擎主要是由一个名叫Nikolaus Gebhardt奥地利人所设计,是sourceforge上的一个开源项目 ...

  7. lua源码分析 伪索引

    Lua 提供了一个 注册表, 这是一个预定义出来的表, 可以用来保存任何 C 代码想保存的 Lua 值. 这个表可以用有效伪索引 LUA_REGISTRYINDEX 来定位. 任何 C 库都可以在这张 ...

  8. bleve搜索引擎源码分析之索引——mapping和lucene一样,也有_all

    例子: package main import ( "fmt" "github.com/blevesearch/bleve" ) func main() { / ...

  9. 4 weekend110的textinputformat对切片规划的源码分析 + 倒排索引的mr实现 + 多个job在同一个main方法中提交

    好的,现在,来weekend110的textinputformat对切片规划的源码分析, Inputformat默认是textinputformat,一通百通. 这就是今天,weekend110的te ...

随机推荐

  1. Linux java 启动脚本

    #!/bin/bash export LANG=en_US.UTF8 start(){ ulimit -n 65535 #find the jars jar_lib=`ls -1 lib/*.jar` ...

  2. echarts 图表用例

    参考博客:http://blog.csdn.net/verne_feng/article/details/51731653 http://echarts.baidu.com/echarts2/doc/ ...

  3. BZOJ 1090 字符串折叠(Hash + DP)

    题目链接 字符串折叠 区间DP.$f[l][r]$为字符串在区间l到r的最小值 正常情况下 $f[l][r] = min(f[l][r], f[l][l+k-1]+f[l+k][r]);$ 当$l$到 ...

  4. css3的一些新属性及部分用法

    CSS3是CSS(层叠样式表)技术的升级版本,增加了很多新属性,我们在web开发中采用css3技术可以提高程序的性能以及用户体验.而且一般面试中会问到知道哪些新增加的属性,我们不可能将所有东西一一复述 ...

  5. codevs——1297 硬币

    1297 硬币  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解       题目描述 Description 我们知道即使是同一种面值的硬币,它们的重量也 ...

  6. 一步步走向国际乱码大赛-- 恶搞C语言

    大家都一直强调规范编码.可是这个世界上有个大师们娱乐的竞赛--国际乱码大赛. 能写出来的都是对语言深入了解的master.我从没想自己也能"恶搞"C,一直都是老老实实编码.就在前几 ...

  7. Hbase调用JavaAPI实现批量导入操作

    将手机上网日志文件批量导入到Hbase中.操作步骤: 1.将日志文件(请下载附件)上传到HDFS中,利用hadoop的操作命令上传:hadoop  fs -put input  / 2.创建Hbase ...

  8. STL algorithm源代码:stl_algo.h

    <span style="font-size:18px;">// Algorithm implementation -*- C++ -*- // Copyright ( ...

  9. SpringBoot学习之启动报错【This application has no explicit mapping for /error.....】

    今天做SpringBoot小例子,在请求controller层的时候出现如下问题. Whitelabel Error Page This application has no explicit map ...

  10. UIAutomation使用測试入门

    自己主动化測试的优点: 1.自己主动化能够自己主动測试,不须要人的干预.同一时候还能够不断地反复某一个动作. 2.自己主动化測试在添加了新的功能之后.还能够回归到原理的功能,使其原来的功能不会受到影响 ...