1. ElasticSearch简介
1.0 MySQL模糊查询的问题
慢
1.1 ElasticSearch是什么
ElasticSearch(简称为es)是一个分布式搜索引擎的底层实现。其底层是Lucene。
1.2 ElasticSearch能做什么
它对任何类型的数据提供了近乎实时的查询功能、分析功能。也就是说,无论你的数据是有结构的,或是没有结构的,是数字类型的数据,或是地理位置数据等等,es都可以把所有这些各式各样的数据,以“特定方式”存储起来,并创建索引。正是因为这个“特定方式”,才使得我们使用es检索数据时,会以最短的时间获取到结果。ElasticSearch的功能,不仅仅是数据检索、数据聚合,es更强大的功能是它能够发现你数据中的趋势。并且当数据量增大时,ElasticSearch天然的分布式特点可以让我们无缝地横向扩展服务。
1.3 ElasticSearch实际应用效果
从这个例子中,我们看到了:分词、相关性排名、高亮、每条搜索记录的部分内容。
1.4 重点概念解释
分词器
后续章节会详细讲解分词器,但是分词器对我们理解es的内容至关重要,所以这里提前讲解一点分词器的内容:
<dependencies>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>7.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers</artifactId>
<version>3.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-highlighter</artifactId>
<version>7.3.1</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>7.3.1</version>
</dependency>
<dependency>
<groupId>com.jianggujin</groupId>
<artifactId>IKAnalyzer-lucene</artifactId>
<version>8.0.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.core.SimpleAnalyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.junit.Test;
import org.wltea.analyzer.lucene.IKAnalyzer;
public class App {
英文分词器:
输入字符串-->分割字符串-->去除停用词
private Analyzer a1 = new StandardAnalyzer();
简单分词器
private Analyzer a2 = new SimpleAnalyzer();
中文分词器(词库分词)
private Analyzer a3 = new IKAnalyzer();
private String text = "What a beautiful girl! How beautiful the girl is!";
我们是中国人";
@Test
public void test() throws Exception {
analyzer(a3, text2);
}
private void analyzer(Analyzer analyzer, String text) throws Exception {
在这里,第一个参数没有实际作用
TokenStream tokenStream = analyzer.tokenStream("content", new StringReader(text));
获取每个单词信息
CharTermAttribute attribute = tokenStream.addAttribute(CharTermAttribute.class);
tokenStream.reset();
while(tokenStream.incrementToken()) {
System.out.println(attribute);
}
tokenStream.end();
tokenStream.close();
}
}
文档
文档,就是要被索引的数据,在被搜索引擎索引之后的一种结构,下面的图有详细的解释,以下是两个原始文档
doc1:
飞雪连天射白鹿
doc2:
胡天八月即飞雪
正向索引
若我们使用mysql中的全文检索,那么mysql会对如上两个原始文档分别进行分词处理,结果如下:
飞雪连连天射白鹿
胡天八月即飞雪
假设我们要搜索的关键字是:飞雪,正向索引就会到第一个文档中去查找“飞雪”这个关键字,如果查找到了,则将第一个文档加入到结果中,再到第二个文档中查找“飞雪”这个关键字,如果查找到了,就将第二个文档加入到结果中。当文档的数量规模上到PB的时候,以正向索引的这种方式进行数据检索的话,效率将会很低!
倒排索引
倒排索引是按照分词与文档的映射建立的,如下:
全文检索基本原理
关键在于:用空间换时间。创建好了倒排索引,在用户查询数据的时候,便可以利用倒排索引大大减少查询的时间。
Lucene中的重点概念
下图展示了很多个Lucene中的概念:
可以看出:
1. 在创建索引时用到了 分词器,在搜索数据时,也用到了分词器
2. 文档是由各个Field组成的,比如上图中的内容、大小、日期
相关性得分
在搜索的时候,输入的搜索内容,如果命中的分词越多,则相关性得分也就越多。比如搜索时如果输入“白鹿在飞雪中奔跑”,而“飞雪连天射白鹿”,就同时命中了“飞雪”和“白鹿”这两个词,而“白鹿原”则只命中了一个“白鹿”,所以前者的相关性得分是大于后者的,最终展现结果的时候,“飞雪连天射白鹿”就会排在“白鹿原”的前面。
2. 安装、启动
es比较吃内存,所以我建议大家为即将安装es的虚拟机设置大一点的内存,将来在安装好es以后,也就可以随时调整es内置的jvm的内存大小了。(-Xms2g -Xmx2g)
软件 | 下载地址 |
ElasticSearch | |
Kibana |
2.1 创建账户
es要求必须以非root账户启动服务,所以我们创建以下账户
adduser elk
passwd elk
2.2 解压ElasticSearch
以root用户登录,上传elasticsearch-7.10.2-linux-x86_64.tar.gz到linux
并将elasticsearch-7.10.2-linux-x86_64.tar.gz移动到elk账户的家目录下
mv elasticsearch-7.10.2-linux-x86_64.tar.gz /home/elk/
进入/home/elk目录,然后解压
tar -zxvf elasticsearch-7.10.2-linux-x86_64.tar.gz
然后授予elk权限
chown -R elk /home/elk/elasticsearch-7.10.2/
2.3 启动es服务
为了让es服务能够被指定机器访问,在es家目录下的config目录下,修改es配置文件:
elasticsearch-7.10.2/config/elasticsearch.yml,可直接把该文件内容整体替换成以下内容
cluster.name: my-application
node.name: node-1
# 允许任何机器链接当前es服务
network.host: 0.0.0.0
http.port: 9200
# 有成为主节点资格的节点列表
# 127.0.0.1和[::1]都代表本机
discovery.seed_hosts: ["127.0.0.1", "[::1]"]
cluster.initial_master_nodes: "node-1"
修改/etc/security/limits.conf,设置系统最大线程个数(否则启动es服务时会报错:max number of threads [2988] for user [elk] is too low, increase to at least [4096]),在该配置文件的末尾追加以下内容:
* soft nofile 65535
* hard nofile 131072
* soft nproc 4096
* hard nproc 4096
修改/etc/sysctl.conf(否则启动es服务时会报错:max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144])
vm.max_map_count=262144
为了加载这个修改,再执行以下命令:
sysctl -p
es服务默认占用9200端口,所以我们要开放9200端口(切换到root用户再执行以下命令):
firewall-cmd --znotallow=public --add-port=9200/tcp --permanent
firewall-cmd --reload
切换到elk用户
su elk
启动es服务
./bin/elasticsearch
访问,能看到以下画面,就说明es服务已经启动成功了!
另外,如果不小心以root用户启动了es服务,那么服务肯定会启动失败的,更重要的是,在es的logs文件夹下也会产生本次启动失败的日志文件,这些日志文件的owner是root,这就导致,就算我们再以elk用户来启动es服务时,仍然会出现“没有权限”的提示,尽管这并不影响es服务的启动。所以每当我们不小心用root启动es服务之后,都应该妥善处理掉那些owner为root的日志文件。
Docker安装ElasticSearch
docker pull elasticsearch:7.11.2
docker run --name es -d -e ES_JAVA_OPTS="-Xms1024m -Xmx1024m" \
-e "discovery.type=single-node" -p 9200:9200 -p 9300:9300 \
elasticsearch:7.11.2
2.4 启动Kibana
切换到root用户
su root
将kibana-7.10.2-linux-x86_64.tar.gz上传到linux,并移动到elk账户的家目录下
mv soft/kibana-7.10.2-linux-x86_64.tar.gz /home/elk/
进入/home/elk目录,解压
tar -zxvf kibana-7.10.2-linux-x86_64.tar.gz
授权
chown -R elk kibana-7.10.2-linux-x86_64
修改Kibana的配置文件config/kibana.yml,可用以下内容直接替换该配置文件中的内容:
# kibana端口
server.port: 5601
# 允许任意远程机器连接kibana
server.host: "0.0.0.0"
# kibana要连接的es服务的url
elasticsearch.hosts: ["http://192.168.3.128:9200"]
elasticsearch.requestTimeout: 60000 # Kibana等待elasticsearch响应的最大时间
切换到elk,进入到Kibana的根目录,执行以下命令,以启动Kibana
./bin/kibana
切换到root,开放5601端口
firewall-cmd --znotallow=public --add-port=5601/tcp --permanent
firewall-cmd --reload
访问:
在首页点击“Dev tools”
点击以下的三角按钮,在右边看到结果,就说明环境搭建全部成功了:
Docker安装Kibana
docker pull kibana:7.11.2
docker run -d -e ELASTICSEARCH_HOSTS=http://192.168.217.128:9200 \
-p 5601:5601 kibana:7.11.2
3. 简单测试
查看所有节点
GET /_cat/nodes?v
查看所有节点的健康情况
GET /_cat/health?v
查看主节点信息
GET /_cat/master?v
查看索引
GET /_cat/indices?v
4. 分词器抢先体验
开篇,就重点介绍了分词器的概念和作用,当时用的是lucene中的分词器,当时是需要自己编码的,而在es中,分词器早已被封装了,我们直接请求即可:
GET _analyze
{
"analyzer": "standard",
"text": "How are you?"
}
GET _analyze
{
"analyzer": "standard",
我是中国人"
}