Elasticsearch简述
Elasticsearch产品介绍
Elasticsearch是一个基于Apache Lucene的开源的分布式搜索和分析引擎,设计用于云计算中,能够快速处理大量数据。它能够近实时地进行复杂的查询,并且可以用于全文检索、结构化搜索以及分析。Elasticsearch具有以下特性:
- 分布式搜索引擎,可以扩展到上百台服务器,处理PB级的数据。
- RESTFUL API,使用JSON进行数据交换。
- 实时分析,可以对数据进行实时分析。
- 高可用性,节点失败时可以自动重分配。
- 近实时,数据被索引后立即可以被搜索。
- 支持各种编程语言。
一、安装运行
-
安装:参照https://www.elastic.co/cn/downloads/elasticsearch,本文版本6.4.3
-
运行:运行bin/elasticsearch,然后就可以访问http://localhost:9200
-
elasticsearch.yml关键配置说明
# 集群名称,判断是否是同一个集群
cluster.name: elasticsearch
# 节点名称,判断是否是集群中的不同节点
#node.name: node-1
# 网络地址和端口,用于http和transport服务使用
network.host: 127.0.0.1
http.port: 9200
# 数据存储地址
#path.data: /path/to/data
# 日志存储地址
#path.logs: /path/to/logs
- Development与Production模式说明
- 以transport的地址是否绑定在localhost为标准判断network.host;
- Development模式下启动时会以warning的方式提示配置检查异常;
- Production模式下启动时会以error的方式提示配置检查异常并退出;
- 参数修改的第二种方式: bin/elasticsearch -E http.port=19200。
- 倒排索引
- 倒排索引是通过分词策略,形成词和文章的映射关系表,这种词典+映射表即为倒排索引。传统的检索是通过文章逐个找到对应关键词的位置。
二、多节点集群
- Elasticsearch本地启动集群的方式
bin/elasticsearch
bin/elasticsearch –E http.port=8200 –E path.data=node2
bin/elasticsearch –E http.port=7200 –E path.data=node3
-
查看集群的详细情况:http://localhost:9200/_cluster/stats
-
查看启动情况:http://localhost:9200/_cat/nodes?v
-
查看集群状态:http://localhost:9200/_cluster/health
status字段指示当前集群在总体上是否正常工作,green表示所有主分片和副本分片都正常运行,yellow表示主分片正常运行,不是所有副本分片都正常运行,red表示有主分片没能正常运行。
- 集群相关概念
- 集群是一组有相同的cluster.name的节点。索引可以被拆分成不同的部分进行存储,称为分片,一个索引的不同分片可以部署到不同的节点,这样可以解决数据量太大,单点存储量有限的问题。每个主分片可以有一个或多个副本分片,可以保证高可用。
- 数据写入流程
- 新建、索引和删除请求都是写操作,必须在主分片上完成后才能被复制到相关的副本分片。客户端请求任意的集群节点(协调节点),协调节点将请求转发到指定的节点,主分片需要将数据保存并发送到副本,副本保存后进行反馈,主分片反馈给客户端,客户端获取反馈。
- 数据读取流程
- 客户端发送查询请求到协调节点,协调节点计算数据所在的分片以及全部的副本位置,为了能够负载均衡,轮询所有节点,将请求发送给具体的节点,节点返回查询结果并反馈给客户端。
- master选举流程
- Elasticsearch的选举流程是由ZenDiscovery模块负责的,主要包含Ping和Unicast单播模块。对所有可以成为master的节点根据nodeId字典排序,每次选举每个节点都把自己所知道的节点排序,然后选出第一个节点暂时认为它是master节点。如果对某个节点的投票数达到一定的值并且该节点自己也选举自己,这个节点就是master。master节点负责集群、节点和索引的管理,不负责文档级别的管理,data节点可以关闭http功能。
- 路由计算
- 通过公式
shard=hash(routing)%number_of_primary_shards
决定文档应该放到哪个分片,routing默认是文档的_id,也可以是自定义的值,通过hash函数获取一个数字,然后获取与主分片数量的余数可以得到文档所在分片的位置。 - 我们可以把请求发送到集群中的任意一个节点,每个节点都有能力处理任意请求,每个节点都知道集群中任一文档的位置,可以直接将请求转发到需要的节点上。
三、Elasticsearch集群脑裂问题
在集群中因为主节点访问阻塞或者网络不可用导致出现分区,不同分区选举出不同的主节点的现象叫做脑裂。脑裂问题可能会导致数据丢失、不一致或者其他问题。
- 脑裂问题的原因
- 网络问题:集群之间的网络延迟导致一些节点访问不到master,认为master挂了然后重新选出了新的master,并对master上的分片和副本标红,分配新的主分片。
- 节点过载:主节点的角色既是master又是data,访问量较大时可能会导致停止响应造成大面积延迟,此时其他节点得不到主节点的响应认为主节点挂掉后会重新选出主节点。
- 内存回收:data节点上的elasticsearch进程占用内存较大,引发JVM的大规模内存回收,造成进程失去响应。
- 解决方案
- 角色分离:master节点与data节点分离,限制角色。
# 主节点配置
node.master: true
node.data: false
# 从节点配置
node.master: false
node.data: true
- 减少误判:discovery.zen.ping_timeout节点状态的响应时间,默认是3s,可以适当调大。如果master在该响应时间的范围内没有做出响应应答,判断该节点已经挂掉了。
- 选举触发:discovery.zen.minimum_master_nodes参数用来控制选举行为发生的最小集群主节点数量。当备选主节点的个数大于等于该参数的值,并且备选主节点中有该参数个节点认为主节点挂了进行选举。
四、Elasticsearch常见操作
文档Document,索引Index,索引中的数据类型Type,文档的属性Field,查询语法Query DSL。
-
create
POST /accounts/person/1
{
"name": "John",
"lastname": "Dow",
"job_description": "System administrator and Linux specialit"
}
-
read
GET /accounts/person/1
-
update
POST /accounts/persion/1/_update
{
"doc": {
"job_description": "System administrator and Linux specialit"
}
}
-
delete
DELETE /accounts/person/1
-
query
-
查询字符串
GET /accounts/person/_search?q=john
-
DSL
GET /accounts/person/_search
{
"query": {
"match": {
"name": "john"
}
}
}
五、ik分词器
- 插件安装:解压插件到elasticsearch安装路径的plugins目录。
- 创建索引库
PUT /ik
{
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1
}
}
- 设置mapping
- ik_smart是粗粒度分词,ik_max_word是细粒度分词。
- type字段类型:Text数据类型用来索引长文本,建立索引前会将文本进行分词,转化为词的组合,建立索引,不能用来排序和聚合。Keyword数据类型用来建立电子邮箱地址、姓名等不需要进行分词的数据,可以用来检索过滤、排序和聚合。
PUT /ik/fulltext/_mapping
{
"properties": {
"content": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_smart"
}
}
}
- 插入数据
POST /ik/fulltext/1
{
"content": "集群之间的网络延迟导致一些节点访问不到master"
}
POST /ik/fulltext/2
{
"content": "认为master挂了然后重新选出了新的master"
}
- 查询
POST /ik/fulltext/_search
{
"query": {
"match": {
"content": "master"
}
},
# 匹配到的结果会添加指定的样式
"highlight": {
"pre_tags": ["<font color='red'>"],
"post_tags": ["</font>"],
"fields": {
"content": {
}
}
}
}
六、Java API访问Elasticsearch
- 创建工程ES-PRAC,引入相关依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.zjh</groupId>
<artifactId>ES-PRAC</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.3.RELEASE</version>
<relativePath/>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 引入elasticsearch依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<!-- 引入jpa操作mysql -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- 在mysql表中创建Blog表
CREATE TABLE `t_blog` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`title` varchar(60) DEFAULT NULL COMMENT '博客标题',
`author` varchar(60) DEFAULT NULL COMMENT '博客作者',
`content` mediumtext COMMENT '博客内容',
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
`update_time` datetime DEFAULT NULL COMMENT '更新时间'