基于Docker环境安装ElasticSearch

1. 搜索技术

搜索技术在我们日常生活的方方面面都会用到,例如:

  • 综合搜索网站:百度、谷歌等
  • 电商网站:京东、淘宝的商品搜索
  • 软件内数据搜索:我们用的开发工具,如Idea的搜索功能

这些搜索业务有一些可以使用数据库来完成,有一些却不行。因此我们今天会学习一种新的搜索方案,解决海量数据、复杂业务的搜索。

1.1.关系型数据库搜索的问题

要实现类似百度的复杂搜索,或者京东的商品搜索,如果使用传统的数据库存储数据,那么会存在一系列的问题:

  • 性能瓶颈:当数据量越来越大时,数据库搜索的性能会有明显下降。虽然可以通过分库分表来解决存储问题,但是性能问题并不能彻底解决,而且系统复杂度会提高、可用性下降。
  • 复杂业务:百度或京东的搜索往往需要复杂的查询功能,例如:拼音搜索、错字的模糊搜索等。这些功能用数据库搜索难以实现,或者实现复杂度较高
  • 并发能力:数据库是磁盘存储,虽然也有缓存方案,但是并不实用。因此数据库的读写并发能力较差,难以应对高并发场景

但是,并不是说数据库就一无是处。在一些对业务有强数据一致性需求,事物需求的情况下,数据库是不可替代的。

只是在海量数据的搜索方面,需要有新的技术来解决,就是我们今天要学习的倒排索引技术。

1.2.倒排索引

倒排索引是一种特殊的数据索引方式,虽然于数据库存储的数据结构没有太大差别,但是在检索方式上却大不一样。

1.2.1.基本概念

先来看两个概念:

  • 文档(Document):用来检索的海量数据,其中的每一条数据就是一个文档。例如一个网页、一个商品信息
  • 词条(Term):对文档数据或用户搜索数据,利用某种算法分词,得到的具备含义的词语就是词条。

例如,数据库中有下面的数据:

idtitle
10谷歌地图之父跳槽FaceBook
20谷歌地图之父加盟FaceBook
30谷歌地图创始人拉斯离开谷歌加盟Facebook
40谷歌地图之父跳槽Facebook与Wave项目取消有关
50谷歌地图之父拉斯加盟社交网站Facebook

那么这里的每一行数据就是一条文档,如:

idtitle
10谷歌地图之父跳槽FaceBook

把标题字段分词,可以得到词语如:谷歌就是一个词条

现在,假设用户要搜索"谷歌创始人跳槽",来看看倒排索引的传统查找在检索时的区别:

1.2.1.传统查找流程

因为复杂搜索往往是模糊的查找,因此数据库索引基本都会实效,只能逐条数据判断。基本流程如下:

1)用户搜索数据,条件是title符合"谷歌创始人跳槽"

2)逐行获取数据,比如id为10的数据

3)判断数据中的title是否符合用户搜索条件

4)如果符合则放入结果集,不符合则丢弃。回到步骤1

如图:

如果有5条数据,则需要遍历并判断5次。如果有100万数据,则需要循环遍历和判断100万次。线性查找和判断,效率极差,一个10mb的硬盘文件,遍历一遍需要3秒。

1.2.2.倒排索引流程

倒排索引的数据存储方式与数据库类似,但检索方式不同。

1.2.2.1.数据存储方式

先看看倒排索引如何处理数据。

文档列表

首先,倒排索引需要把文档数据逐个编号(从0递增),存储到文档表中。并且给每一个编号创建索引,这样根据编号检索文档的速度会非常快。
在这里插入图片描述

词条列表(Term Dictionary):

然后,对文档中的数据按照算法做分词,得到一个个的词条,记录词条和词条出现的文档的编号、位置、频率信息,如图:

image-20200103161448460.png

然后给词条创建索引,这样根据词条匹配和检索的速度就非常快。

1.2.2.2.检索数据过程

倒排索引的检索流程如下:

1)用户输入条件"谷歌创始人跳槽"进行搜索。

2)对用户输入内容分词,得到词条:谷歌创始人跳槽

3)拿着词条到词条列表中查找,可以得到包含词条的文档编号:0、1、2、3、4。

4)拿着词条的编号到文档列表中查找具体文档。

如图:

在这里插入图片描述

虽然搜索会在两张表进行,但是每次都是根据索引查找,因此速度比传统搜索时的全表扫描速度要快的多。

1.3.Lucene

在java语言中,对倒排索引的实现中最广为人知的就是Lucene了,目前主流的java搜索框架都是依赖Lucene来实现的。

  • Lucene是一套用于全文检索和搜寻的开源程序库,由Apache软件基金会支持和提供
  • Lucene提供了一个简单却强大的应用程序接口(API),能够做全文索引和搜寻,在Java开发环境里Lucene是一个成熟的免费开放源代码工具
  • Lucene并不是现成的搜索引擎产品,但可以用来制作搜索引擎产品,比较知名的搜索产品有:Solr、ElasticSearch
  • 官网:http://lucene.apache.org/

企业生产中一般都会使用成熟的搜索产品,例如:Solr或者Elasticsearch,不过从性能来看Elasticsearch略胜一筹,因此我们今天的学习目标就是elasticsearch。

2.ElasticSearch介绍和安装

如果把Lucene比喻成一台发动机,那么Solr就是一台家用汽车,而Elasticsearch就是一台c超级跑车。

2.1.简介

Elastic官网:https://www.elastic.co/cn/

Elastic是一系列产品的集合,比较知名的是ELK技术栈,其核心就是ElasticSearch:

Elasticsearch官网:https://www.elastic.co/cn/products/elasticsearch

1526464283575.png

Elasticsearch是一个基于Lucene的搜索web服务,对外提供了一系列的Rest风格的API接口。因此任何语言的客户端都可以通过发送Http请求来实现ElasticSearch的操作

ES的主要优势特点如下:

  • 速度快:Elasticsearch 很快,快到不可思议。我们通过有限状态转换器实现了用于全文检索的倒排索引,实现了用于存储数值数据和地理位置数据的 BKD 树,以及用于分析的列存储。而且由于每个数据都被编入了索引,因此您再也不用因为某些数据没有索引而烦心。您可以用快到令人惊叹的速度使用和访问您的所有数据。实现近实时搜索,海量数据更新在Elasticsearch中几乎是完全同步的。
  • 扩展性高:可以在笔记本电脑上运行,也可以在承载了 PB 级数据的成百上千台服务器上运行。原型环境和生产环境可无缝切换;无论 Elasticsearch 是在一个节点上运行,还是在一个包含 300 个节点的集群上运行,您都能够以相同的方式与 Elasticsearch 进行通信。它能够水平扩展,每秒钟可处理海量事件,同时能够自动管理索引和查询在集群中的分布方式,以实现极其流畅的操作。天生的分布式设计,很容易搭建大型的分布式集群(solr使用Zookeeper作为注册中心来实现分布式集群)
  • 强大的查询和分析:通过 Elasticsearch,您能够执行及合并多种类型的搜索(结构化数据、非结构化数据、地理位置、指标),搜索方式随心而变。先从一个简单的问题出发,试试看能够从中发现些什么。找到与查询最匹配的 10 个文档是一回事。但如果面对的是十亿行日志,又该如何解读呢?Elasticsearch 聚合让您能够从大处着眼,探索数据的趋势和模式。如全文检索,同义词处理,相关度排名,复杂数据分析。
  • 操作简单:客户端API支持Restful风格,简单容易上手。

使用ES的案例场景:

1、GitHub抛弃了Solr,采取ElasticSearch 来做PB级的搜索。 “GitHub使用ElasticSearch搜索20TB 的数据,包括13亿文件和1300亿行代码”

2、维基百科:启动以elasticsearch为基础的核心搜索架构

3、SoundCloud:“SoundCloud使用ElasticSearch为1.8亿用户提供即时而精准的音乐搜索服务”

4、百度:百度目前广泛使用ElasticSearch作为文本数据分析,采集百度所有服务器上的各类指标数据及用户自定义数据,通过对各种数据进行多维分析展示,辅助定位分析实例异常或业务层面异常。目前覆盖百度内部20多个业务线(包括casio、云分析、网盟、预测、文库、直达号、钱包、风控等),单集群最大100台机器,200个ES节点,每天导入30TB+数据。 新浪使用ES 分析处理32亿条实时日志。

5、阿里使用ES 构建自己的日志采集和分析体系

6、京东到家订单中心 Elasticsearch 演进历程

Elasticsearch 做为一款功能强大的分布式搜索引擎,支持近实时的存储、搜索数据,在京东到家订单系统中发挥着巨大作用,目前订单中心ES集群存储数据量达到10亿个文档,日均查询量达到5亿。

7、滴滴 2016 年初开始构建 Elasticsearch 平台,如今已经发展到超过 3500+ Elasticsearch 实例,超过 5PB 的数据存储,峰值写入 tps 超过了 2000w/s 的超大规模。

8、携程Elasticsearch应用案例

9、去哪儿:订单中心基于elasticsearch 的解决方案

。。。。。。。

本章是基于Docker安装

2.1 安装ElasticSearch

docker run -id --name elasticsearch \
    -e "cluster.name=elastic-cluster" \
    -e "http.host=0.0.0.0" \
    -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
    -e "discovery.type=single-node" \
    -e http.cors.enabled=true \
    -e http.cors.allow-origin="*" \
    -e http.cors.allow-headers=X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization \
    -e http.cors.allow-credentials=true \
    -v es-data:/usr/share/elasticsearch/data \
    -v es-logs:/usr/share/elasticsearch/logs \
    -v es-plugins:/usr/share/elasticsearch/plugins \
    --privileged \
    --hostname elasticsearch \
    -p 9200:9200 -p 9300:9300 elasticsearch:7.4.2
    
​

命令解释:

  • -e "cluster.name=es-docker-cluster":设置集群名称
  • -e "http.host=0.0.0.0":监听的地址,可以外网访问
  • -e "ES_JAVA_OPTS=-Xms512m -Xmx512m":内存大小
  • -e "discovery.type=single-node":非集群模式
  • -v es-data:/usr/share/elasticsearch/data:挂载逻辑卷,绑定es的数据目录
  • -v es-logs:/usr/share/elasticsearch/logs:挂载逻辑卷,绑定es的日志目录
  • -v es-plugins:/usr/share/elasticsearch/plugins:挂载逻辑卷,绑定es的插件目录
  • --privileged:授予逻辑卷访问权
  • -p 9200:9200:端口映射配置

restart相关参数如下:

选项作用
–restart=no不自动重启容器. (默认)
–restart=on-failure容器发生error而退出(容器退出状态不为0)重启容器
on-failure:3在容器非正常退出时重启容器,最多重启3次
–restart=unless-stopped在容器退出时总是重启容器,但是不考虑在Docker守护进程启动时就已经停止了的容器
–restart=always在容器已经stop掉或Docker stoped/restarted的时候才重启容器

如果已经启动的容器项目,则使用update更新:

docker update --restart=always 容器名/ID

防火墙配置:

# 开放端口 9200  9300 5601
firewall-cmd --zone=public --add-port=9200/tcp --permanent
# 重启防火墙
firewall-cmd --reload
# 查看放行端口
firewall-cmd --list-ports

2.2 Kibana

ES提供了多种访问方式,官方推荐使用REST API,也是使用人数最多的访问方式。就是通过http协议,使用Restful的风格,按照es的api去操作数据,访问时我们需要传递给es json 参数,es处理后会给我们返回 json 的结果,不过浏览器不方便操作es 官方推荐使用kibana来操作ES

2.2.1 Kibana简介

1526481256534-5439065.png

Kibana是一个基于Node.js的Elasticsearch索引库数据统计工具,可以利用Elasticsearch的聚合功能,生成各种图表,如柱形图,线状图,饼图等。

而且还提供了操作Elasticsearch索引数据的控制台,并且提供了一定的API提示,非常有利于我们学习Elasticsearch的语法。

2.2.2 安装Kibana

# 可以指定es地址:-e ELASTICSEARCH_URL=http://192.168.200.150:9200 
​
# es和kibana在同一docker下 
# 可以直接: --link后面的 es容器的名称:elasticsearch
​
docker run -di --name kibana -p 5601:5601 --link elasticsearch:elasticsearch   kibana:7.4.2  
# Head 插件(了解)
docker run -d --name es_admin -p 9100:9100 mobz/elasticsearch-head:5

输入地址访问:http://192.168.200.150:5601

2.3 分词器

根据我们之前讲解的倒排索引原理,当我们向elasticsearch插入一条文档数据时,elasticsearch需要对数据分词,分词到底如何完成呢?

ElasticSearch 内置分词器

  • Standard Analyzer - 默认分词器,按词切分,小写处理
  • Simple Analyzer - 按照非字母切分(符号被过滤), 小写处理
  • Stop Analyzer - 小写处理,停用词过滤(the,a,is)
  • Whitespace Analyzer - 按照空格切分,不转小写
  • Keyword Analyzer - 不分词,直接将输入当作输出
  • Patter Analyzer - 正则表达式,默认\W+(非字符分割)
  • Language - 提供了30多种常见语言的分词器

2.3.1 默认的分词器

kibana中可以测试分词器效果,我们来看看elasticsearch中的默认分词器。

在kibana的DevTools中输入一段命令:

POST /_analyze
{
  "text": "学习java太棒了",
  "analyzer": "standard"
}

请求代表的含义:

  • 请求方式:POST

  • 请求路径:_analyze,前面省略了http://127.0.0.1:9200,这个由Kibana帮我们补充

  • 请求参数:风格,包含两个属性:

    • analyzer:分词器名称,standard是默认的标准分词器
    • text:要分词的文本内容

效果:

  • 按词切分
  • 单词大写变小写

2.3.2 IK分词器

标准分词器并不能很好处理中文,一般我们会用第三方的分词器,例如:IK分词器。

IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包,是一个基于Maven构建的项目,具有60万字/秒的高速处理能力,支持用户词典扩展定义。

IK分词器的 地址:https://github.com/medcl/elasticsearch-analysis-ik, 安装非常简单。

IK分词器可以用ik_max_wordik_smart两种方式,分词粒度不同。

2.3.2.1 安装IK分词器

1、安装ik插件(在线较慢)

# 进入容器内部
docker exec -it elasticsearch /bin/bash
​
# 在线下载并安装
./bin/elasticsearch-plugin  install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.4.2/elasticsearch-analysis-ik-7.4.2.zip
​
#退出
exit
#重启容器
docker restart elasticsearch

2、离线安装ik插件(推荐)

# 1、进入/var/lib/docker/volumes/es-plugins/_data/
cd /var/lib/docker/volumes/es-plugins/_data/
# 2、新建文件目录 ik 并且进入
mkdir ik
cd ik

# 3、解压elasticsearch-analysis-ik-7.4.2.zip
yum -y install unzip 
unzip elasticsearch-analysis-ik-7.4.2.zip

# 4、重启容器
docker restart elasticsearch
# 查看es日志
docker logs -f elasticsearch

image-20200405012258985.png

# 重启 Kibana
docker restart kibana

测试:

GET /_analyze
{
  "analyzer": "ik_max_word",
  "text": "程序员学习java太棒了"
}

结果:

{
  "tokens" : [
   
    {
      "token" : "程序员",
      "start_offset" : 2,
      "end_offset" : 5,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "程序",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "员",
      "start_offset" : 4,
      "end_offset" : 5,
      "type" : "CN_CHAR",
      "position" : 3
    },
    {
      "token" : "学习",
      "start_offset" : 5,
      "end_offset" : 7,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "java",
      "start_offset" : 7,
      "end_offset" : 11,
      "type" : "ENGLISH",
      "position" : 5
    },
    {
      "token" : "太棒了",
      "start_offset" : 11,
      "end_offset" : 14,
      "type" : "CN_WORD",
      "position" : 6
    },
    {
      "token" : "太棒",
      "start_offset" : 11,
      "end_offset" : 13,
      "type" : "CN_WORD",
      "position" : 7
    },
    {
      "token" : "了",
      "start_offset" : 13,
      "end_offset" : 14,
      "type" : "CN_CHAR",
      "position" : 8
    }
  ]
}

小结:

  • ik_smart:最小切分
  • ik_max_word:最细切分
2.3.2.2 扩展词词典

随着社会的发展,在原有的词汇列表中不是一个词的,但是现在已经是一个词了。比如:“白富美”,“高富帅” 等。

所以我们的词汇也需要不断的更新,IK分词器提供了扩展词汇的功能。

1)打开IK分词器config目录:

image-20201115230147799.png

2)IKAnalyzer.cfg.xml配置文件内容添加:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
        <comment>IK Analyzer 扩展配置</comment>
        <!--用户可以在这里配置自己的扩展字典 *** 添加扩展词典-->
        <entry key="ext_dict">ext.dic</entry>
         <!--用户可以在这里配置自己的扩展停止词字典-->
        <entry key="ext_stopwords"></entry>
        <!--用户可以在这里配置远程扩展字典 -->
        <!-- <entry key="remote_ext_dict">words_location</entry> -->
        <!--用户可以在这里配置远程扩展停止词字典-->
        <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

3)新建一个 ext.dic,可以参考config目录下复制一个配置文件进行修改

程序员
高富帅
白富美
我是一个爱学习的程序员

4)重启elasticsearch

docker restart elasticsearch
docker restart kibana

# 查看 日志
docker logs -f elasticsearch

image-20201115230900504.png

日志中已经成功加载ext.dic配置文件

5)测试效果:

GET /_analyze
{
  "analyzer": "ik_max_word",
  "text": "程序员里面也有高富帅,不知道有没有白富美"
}

注意当前文件的编码必须是 UTF-8 格式,严禁使用Windows记事本编辑

2.3.2.3 停用词词典

在互联网项目中,在网络间传输的速度很快,所以很多语言是不允许在网络上传递的,如:关于宗教、政治等敏感词语,那么我们在搜索时也应该忽略当前词汇。

IK分词器也提供了强大的停用词功能,让我们在索引时就直接忽略当前的停用词汇表中的内容。

1)IKAnalyzer.cfg.xml配置文件内容添加:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
        <comment>IK Analyzer 扩展配置</comment>
        <!--用户可以在这里配置自己的扩展字典-->
        <entry key="ext_dict">ext.dic</entry>
         <!--用户可以在这里配置自己的扩展停止词字典  *** 添加停用词词典-->
        <entry key="ext_stopwords">stopword.dic</entry>
        <!--用户可以在这里配置远程扩展字典  -->
        <!-- <entry key="remote_ext_dict">words_location</entry> -->
        <!--用户可以在这里配置远程扩展停止词字典-->
        <!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>

3)在 stopword.dic 添加停用词

特朗普选举

4)重启elasticsearch

docker restart elasticsearch
docker restart kibana
​
# 查看 日志
docker logs -f elasticsearch

日志中已经成功加载stopword.dic配置文件

5)测试效果:

GET /_analyze
{
  "analyzer": "ik_max_word",
  "text": "特朗普选举失败"
}

注意当前文件的编码必须是 UTF-8 格式,严禁使用Windows记事本编辑

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

also&lucky

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值