Elasticsearch ——让你的搜索引擎全面发展!

邱凯
原创 1798       2019-01-09  


你看过《无敌破坏王2》吗?电影里对互联网每一个节点的具象化表现,真的是脑洞大开!


每一个上网用户都被具化成实体,乘坐交通工具在每一个站点「停留」,网页上的广告位变成推销小哥举着牌子给用户推销,感兴趣的人就跟着这个小哥坐车去他简陋的小网站。细思极有趣。


当然,这里最让人印象深刻的就是这个搜索引擎——万事通(knowsmore),他是一个资料库柜台的小人,人们来这提问,他就搜索路径,让他们上车去往下一站。


最有趣的一点,是你每说一个字,他就会猜测一大堆的词语、句子,把搜索引擎的联想功能展现得特别生动,一副「本能联想」的表情让你哭笑不得。


这个看起来什么都知道的搜索引擎背后,除了数据,还有什么在支撑呢?Elasticsearch了解一下!

Elasticsearch的使用分享


Elasticsearch是一个建立在全文搜索引擎 Apache Lucene(TM) 基础上的搜索引擎。当然 Elasticsearch 并不仅仅是 Lucene 那么简单,它不仅包括了全文搜索功能,还可以做分布式实时文件存储,并将每一个字段都编入索引,使其可以被搜索,做实时分析的分布式搜索引擎,可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据。Elasticsearch 是面向文档的,文档中存储的数据结构,与面向对象的数据结构是一样的,基于这种文档数据结构,es可以提供复杂的索引,全文检索,分析聚合等功能。它使用json数据格式来表达,利用倒排索引去实现对大量数据的快速索引。


在Elasticsearch 的使用过程中,做bulk多线程批量插入的时候,会遇到内存溢出的情况,在检索的过程中会出现检索缓慢,这是因为内存的原因。大家都知道Elasticsearch 的使用对内存的要求和依赖会比较高。另一方面,Elasticsearch 的检索免不了分词进行中文的模糊检索,所以这里分享一下关于Elasticsearch 的内存的一些经验和分词检索的使用经验。


Elasticsearch的内存分配 


Elasticsearch 在安装后默认会设置内存为1G


但是对于现实的业务场景,这个默认的内存设置很快会出现问题,elasticsearch的查询还是靠的内存,所以我们需要修改elasticsearch的堆内存,一个方法指定ES_HEAP_SIZE的环境变量,可以用 export ES_HEAP_SIZE = 10g

还可以通过另一种方式,可以直接在启动elasticsearch的时候将内存大小设定,./elasticsearch -Xmx 10g -Xms 10g , 这里我们最好设置Xmx和Xms的大小是相同的,其目的是为了能够在java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小而浪费资源,可以减轻伸缩堆大小带来的压力。


说完elasticsearch 自身服务的内存设置,再说一下如何在一台机器中如何给elasticsearch分配内存吧!


我们都知道对于elasticsearch来说,内存很重要,但把机器内存全给它好吗?不,因为还有另一个内存消耗的Lucene,Lucene的设计是把底层OS里的数据缓存到内存中,它的性能取决于和OS的交互,如果把内存都给了elasticsearch,lucene得到的内存会很少,全文检索的性能会很差。所以如果机器完全是给elasticsearch检索使用,分配50%的内存给elasticsearch,剩下的50%内存会被lucene使用用于文件的缓存,提高性能。


还有一点,我们在对elasticsearch运行的过程中,需要禁用swapping,禁止内存交换到磁盘上,我们可以在启动es前,修改配置文件elasticsearch.yml的mlockall开关:

Bootstarp.mlockall : true


Elasticsearch的分词索引


在我们的实际项目中,我们利用了elasticsearch 去完成去资讯的检索,在设计过程中,考虑到检索的性能和效率,之前的因为数据全部堆积在一个索引上,随着数据的增加,elasticsearch的检索的效率非常低,100G以内的一个索引的性能都不会受到很大的影响,所以在设计过程中,我这边设计为每个月创建一个索引,将所有索引都取同一个别名,这样我们查询别名就可以查询所有别名下的索引,保证了每一个索引的性能和效率,第一个索引和对应的mapping都手动创建,在代码中,写入elasticsearch中时,去每个月的第一个天,去代码自动创建新的索引:


在资讯的全文检索过程中,我遇到了一些问题,因为金融的资讯的实时性要求比较高,在资讯检索的过程中,我先前用了ik-max-word去对检索的内容进行分词,如果按照资讯的时间进行排序,检索出来的资讯的相关度比较差,进过排查,ik-max-word的分词主要依赖于词库,需要不断丰富词库的同时,还会分词出不必要的词汇,比如恒生电子,会分词为恒生电子,恒生,电子这样三个词,再去检索的过程中,满足这三个词的任意一种都会被检索出来,按照时间优先排序,得分次排序的话,匹配出来的可能不是关联度高的,这样问题就显示的比较明显。


在优化过程中,将ik-max-word分词换成ik-smart,将mapping也修改为ik-smart去分词


得到结果后,再利用bool去检索


这样对前一版本的检索进行了结果的优化,但是ik-smart 对句子的解析的能力是比较弱的,我们就可以猜想引用nlp的能力去完成对该功能的优化。


建议如果去安装elasticsearch 6.x版本,对底层的lucene做了性能的优化,对mapping的string做了改动,检索的性能比2.x的老版本有大幅度的增加,笔者这边由于之前的数据量,正在研究2.3.3 数据升级到 6.x 版本演示,分词的检索,6.x支持hanlp的插件,感兴趣的小伙伴可以后台留言一起加入研究!让我们一起打造一个real knowsmore吧!

恒生技术之眼原创文章,未经授权禁止转载。详情见转载须知

联系我们

恒 生 技 术 之 眼