- 18
- 0
- 约2.06千字
- 约 5页
- 2017-06-13 发布于湖北
- 举报
如何快速实现⾼并发短⽂检索
⼀、需求缘起
某并发量很⼤,数据量适中的业务线需要实现⼀个“标题检索”的功能:
(1)并发量较⼤, 秒20w次
(2 )数据量适中,⼤概200w数据
(3 )是否需要分词:是
(4 )数据是否实时更新:否
⼆、常见潜在解决⽅案及优劣
(1)数据库搜索法
具体⽅法:将标题数据存放在数据库中,使⽤like来检索
优点:⽅案简单
缺点:不能实现分词,并发量扛不住
(2 )数据库全⽂检索法
具体⽅法:将标题数据存放在数据库中,建⽴全⽂索引来检索
优点:⽅案简单
缺点:并发量扛不住
(3 )使⽤开源⽅案将索引外置
具体⽅法:搭建lucene ,solr ,ES等开源外置索引⽅案
优点:性能⽐上⾯两种好
缺点:并发量可能有风险,系统⽐较重,为⼀个简单的业务搭建⼀套这样的系统成本
较⾼
、58龙哥的建议
问1 :龙哥,58同城第⼀届编程⼤赛的题⽬好像是“黄反词过滤” ,你是冠军,当时是
⽤DAT来实现的么?
龙哥:是的
画外⾳:什么是DAT?
普及:DAT是double array trie的缩写,是trie树的⼀个变体优化数据结构,它在保证trie
树检索效率的前提下,能⼤⼤减少内存的使⽤,经常⽤来解决检索,信息过滤等问
题。 (具体⼤伙百度⼀下“DAT” )
问2 :上⾯的业务场景可以使⽤DAT来实现么?
龙哥:DAT更新数据⽐较⿇烦,不能增量
问3 :那直接使⽤trie树可以么?
龙哥:trie树⽐较占内存
画外⾳:什么是trie树?
普及:trie树,又称单词查找树,是⼀种树形结构,是⼀种哈希树的变种。典型应⽤是
⽤于统计,保存⼤量的字符串 (但不仅限于字符串),所以经常被搜索引擎系统⽤于
⽂本词频统计。它的优点是:利⽤字符串的公共前缀来减少查询时间,最⼤限度地减
少⽆谓的字符串⽐较,查询效率⽐哈希树⾼。 (来源:百度百科)
例如:上⾯的trie树就能够表⽰ {and as at cn com }这样5个标题的集合。
问4 :如果要⽀持分词,多个分词遍历trie树,还需要合并对吧?
龙哥:没错, 个分词遍历⼀次trie树,可以得到doc_id的list ,多个分词得到的list合
并,就是最终的结果。
问5 :龙哥,还有什么更好,更轻量级的⽅案么?
龙哥:⽤trie树,数据会膨胀⽂档数*标题长度这么多,标题越长,⽂档数越多,内存
占⽤越⼤。有个⼀个⽅案,内存量很⼩,和标题长度⽆关,⾮常帅⽓。
问6 :有相关⽂章么,推荐⼀篇?
龙哥:可能⽹上没有,我简单说⼀下吧,核⼼思想就是“ 内存hash + ID list”
索引初始化步骤为:对所有标题进⾏分词,以词的hash为key ,doc_id的集合为value
查询的步骤为:对查询词进⾏分词,对分词进⾏hash ,直接查询hash表格,获取
doc_id的list ,然后多个词进⾏合并
=====例⼦=====
例如:
doc 1 : 我爱北京
doc2 : 我爱到家
doc3 : 到家美好
先标题进⾏分词:
doc 1 : 我爱北京 - 我,爱,北京
doc2 : 我爱到家 - 我,爱,到家
doc3 : 到家美好 - 到家,美好
对分词进⾏hash ,建⽴hash + ID list :
hash(我) - {doc 1 doc2}
hash(爱) - {doc 1 doc2}
hash(北京) - {doc 1}
hash(到家) - {doc2 doc3}
hash(美好) - {doc3}
这样,所有标题的初始化就完毕了,你会发现,数据量和标题的长度没有关系。
⽤户输⼊“我爱” ,分词后变为{我,爱} ,对各个分词的hash进⾏内存检索
hash(我)-{doc 1 doc2}
hash(爱)-{doc 1 doc2}
然后进⾏合并,得到最后的查找结果是doc 1+doc2 。
=====例⼦END=====
问7 :这个⽅法有什么优点呢?
龙哥:存内存操作,能满⾜很⼤的并发,时延也很低,占⽤内存也不⼤,实现⾮常简
单快速
问8 :有什么不⾜呢?和传统搜索有什么区别咧?
龙哥:这是⼀个快速过度⽅案,因为索引本⾝没有落地,还是需要在数据库中存储固
化的标题数据,如果不做⾼可⽤,数据恢复起来会⽐较慢。当然做⾼可⽤也是很容易
的,建⽴两份⼀样的hash索引即可。另外,没有做⽔平切分,但数据量⾮常⾮常⾮常
⼤时,还是要做⽔平切分改进的。
欢迎加⼊我的社群或关注公众号“架构师之路”进⾏讨论。
W3Cscho
原创力文档

文档评论(0)