elasticsearch学习和实践01

es学习笔记记录整理,不定期更新

文章目录

    • 1. Elastic Stack介绍
    • 2. Elasticsearch
      • 2.1 介绍
      • 2.2 安装
        • 2.2.1 版本说明
        • 2.2.2 单机版安装
        • 2.2.3 elasticsearch-head
      • 2.3 基本概念
      • 2.4 RESTful API
        • 2.4.1 创建非结构化索引
        • 2.4.2 插入数据
        • 2.4.3 更新数据
        • 2.4.4 删除数据
        • 2.4.5 搜索数据
          • 根据id搜索数据
          • 搜索全部数据
          • 关键字搜索数据
        • 2.4.6 DSL搜索
          • 实现:查询年龄大于30岁的男性用户
          • 全文检索
          • 2.4.7 高亮显示
        • 2.4.8 聚合
    • 3 核心详解
      • 3.1 文档
      • 3.2 查询响应
        • 3.2.1 pretty
        • 3.2.2 指定响应字段
      • 3.3 判断文档是否存在
      • 3.4 批量操作
        • 3.4.1 批量查询
        • 3.4.2 _bulk操作
      • 3.5 分页
      • 3.6 映射
      • 3.7 结构化查询
        • 3.7.1 term查询
        • 3.7.2 terms查询
        • 3.7.3 range查询
        • 3.7.4 exists查询
        • 3.7.5 match查询
        • 3.7.6 bool查询
      • 3.8 过滤查询
    • 4 中文分词
      • 4.1 分词
      • 4.2 分词API
      • 4.3 中文分词
    • 5 全文搜索
      • 5.1 单词搜索
      • 5.2 多词搜索
      • 5.4 组合搜索
      • 5.5 权重
    • 6 es集群
      • 6.1 集群节点
      • 6.2 搭建集群
      • 6.3 分片和副本
      • 6.4 故障转移
      • 6.5 分布式文档
        • 6.5.1 路由
        • 6.5.2 文档的写操作
        • 6.5.3 搜索文档(单个文档)
        • 6.5.4 全文搜索
    • 7. java客户端
    • 8. 生产配置
      • 1. stop命令
      • 2. elasticsearch.yml
    • 9. 调优
    • 参考

1. Elastic Stack介绍

ELK,分别是Elasticsearch、Logstash、Kibana组成 ,之后又有新成员Beats的加入,所以就形成了Elastic Stack。

Elasticsearch

Elasticsearch 基于java,是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,restful风格接口,多数据源,自动搜索负载等。

Logstash

Logstash 基于java,是一个开源的用于收集,分析和存储日志的工具

Kibana

Kibana 基于nodejs,也是一个开源和免费的工具,Kibana可以为 Logstash 和 ElasticSearch 提供的日志分析友好的Web 界面,可以汇总、分析和搜索重要数据日志

Beats

Beats是elastic公司开源的一款采集系统监控数据的代理agent,是在被监控服务器上以客户端形式运行的数据收集器的统称,可以直接把数据发送给Elasticsearch或者通过Logstash发送给Elasticsearch,然后进行后续的数据分析活动 。

Beats由如下组成:

  • Packetbeat:是一个网络数据包分析器,用于监控、收集网络流量信息,Packetbeat嗅探服务器之间的流量,解析应用层协议,并关联到消息的处理,其支 持ICMP (v4 and v6)、DNS、HTTP、Mysql、PostgreSQL、Redis、MongoDB、Memcache等协议;
  • Filebeat:用于监控、收集服务器日志文件,其已取代 logstash
  • Metricbeat:可定期获取外部系统的监控指标信息,其可以监控、收集 Apache、HAProxy、MongoDB、MySQL、Nginx、PostgreSQL、Redis、System、Zookeeper等服务
  • Winlogbeat:用于监控、收集Windows系统的日志信息

2. Elasticsearch

2.1 介绍

Elastic Stack的核心,全文搜索引擎。官网:https://www.elastic.co/cn/products/elasticsearch

2.2 安装

2.2.1 版本说明

目前主流版本:7.2.0

2.2.2 单机版安装
#创建elsearch用户以及主目录,Elasticsearch不支持root用户运行
useradd -d /home/es -m elasticsearch
# 设置密码 12345678即可
passwd elasticsearch

#下载
cd /home/es
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.2.0-linux-x86_64.tar.gz
#解压安装包
tar -zxvf elasticsearch-7.2.0-linux-x86_64.tar.gz 
#修改配置文件
vim config/elasticsearch.yml
network.host: 0.0.0.0 #设置ip地址,任意网络均可访问
#修改jvm启动参数
vim conf/jvm.options
-Xms128m #根据自己机器情况修改
-Xmx128m

# ===== root用户下的操作 ======
# 修改文件描述符 设定同一时间打开的文件数的最大值为65535
vim /etc/profile
ulimit -n 65536
# 生效
source /etc/profile
# 修改limits.conf
vim  /etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536

# 验证
ulimit -a
# 修改 最大映射数量 MMP
vim /etc/sysctl.conf
vm.max_map_count=262144
# 生效
sysctl -p 

# ====启动服务====
su - elasticsearch
cd /home/es/elasticsearch-7.2.0-linux-x86_64/bin
./elasticsearch 或 ./elasticsearch -d #后台启动

elasticsearch.yml可参考

cluster.name: cms
network.host: 0.0.0.0

# custom config
node.name: "node-1"
discovery.seed_hosts: ["127.0.0.1", "[::1]"]
cluster.initial_master_nodes: ["node-1"]
# 开启跨域访问支持,默认为false
http.cors.enabled: true
# 跨域访问允许的域名地址,(允许所有域名)以上使用正则
http.cors.allow-origin: /.*/ 
2.2.3 elasticsearch-head

ES官方并没有为ES提供界面管理工具,仅仅是提供了后台的服务。elasticsearch-head是一个为ES开发的一个页
面客户端工具,其源码托管于GitHub,地址为:https://github.com/mobz/elasticsearch-head

建议通过docker或Chrome插件安装

docker安装

#拉取镜像
docker pull mobz/elasticsearch-head:5
#创建容器
docker create --name elasticsearch-head -p 9100:9100 mobz/elasticsearch-head:5
#启动容器
docker start elasticsearch-head

docker安装可能出现的问题:

问题: 使用 Elasticsearch Head 查看“数据浏览”时,右侧不出数据,使用浏览器F12查看后,发现 406 Not Acceptable 错误

解决:

  1. 进入 es-head 安装目录;

  2. cd _site/

  3. 编辑 vendor.js 共有两处:

    将 6886行 contentType: “application/x-www-form-urlencoded” 修改为 contentType: “application/json;charset=UTF-8”

    将 7574行 var inspectData = s.contentType === “application/x-www-form-urlencoded” && 修改为 var inspectData = s.contentType === “application/json;charset=UTF-8” &&

  4. 刷新浏览器验证

elasticsearch学习和实践01_第1张图片

2.3 基本概念

索引

  • 索引(index)是Elasticsearch对逻辑数据的逻辑存储,所以它可以分为更小的部分
  • 可以把索引看成关系型数据库的表,索引的结构是为快速有效的全文索引准备的,特别是它不存储原始值
  • Elasticsearch可以把索引存放在一台机器或者分散在多台服务器上,每个索引有一或多个分片(shard),每个分片可以有多个副本(replica)

文档

  • 存储在Elasticsearch中的主要实体叫文档(document)。用关系型数据库来类比的话,一个文档相当于数据库表中的一行记录

  • Elasticsearch和MongoDB中的文档类似,都可以有不同的结构,但Elasticsearch的文档中,相同字段必须有相同类型

  • 文档由多个字段组成,每个字段可能多次出现在一个文档里,这样的字段叫多值字段(multivalued)

  • 每个字段的类型,可以是文本、数值、日期等。字段类型也可以是复杂类型,一个字段包含其他子文档或者数组

映射

  • 所有文档写进索引之前都会先进行分析,如何将输入的文本分割为词条、哪些词条又会被过滤,这种行为叫做映射(mapping)。一般由用户自己定义规则

文档类型

  • 在Elasticsearch中,一个索引对象可以存储很多不同用途的对象。例如,一个博客应用程序可以保存文章和评论
  • 每个文档可以有不同的结构
  • 不同的文档类型不能为相同的属性设置不同的类型。例如,在同一索引中的所有文档类型中,一个叫title的字段必须具有相同的类型

2.4 RESTful API

在Elasticsearch中,提供了功能丰富的RESTful API的操作,包括基本的CRUD、创建索引、删除索引等操作

7.x以后的更新:

  • 索引操作:PUT {index}/{type}/{id}需要修改成PUT {index}/_doc/{id}
  • Mapping 操作:PUT {index}/{type}/_mapping 则变成 PUT {index}/_mapping
  • 所有增删改查搜索操作返回结果里面的关键字 _type 都将被移除
2.4.1 创建非结构化索引

在Lucene中,创建索引是需要定义字段名称以及字段的类型的,在Elasticsearch中提供了非结构化的索引,就是不
需要创建索引结构,即可写入数据到索引中,实际上在Elasticsearch底层会进行结构化操作,此操作对用户是透明

创建空索引 :

PUT /haoke
{
    "settings": {
        "index": {
            "number_of_shards": "2", #分片数
            "number_of_replicas": "0" #副本数
        }
    }
} 

#删除索引
DELETE /haoke
{
	"acknowledged": true
}
2.4.2 插入数据

url规则:POST /{索引}/{类型}/{id} 7.x以后为/{索引}/_doc/{id}

POST /haoke/user/1001
#数据
{
    "id":1001,
    "name":"张三",
    "age":20,
    "sex":"男"
} 

#响应
{
    "_index": "haoke",
    "_type": "user",
    "_id": "1",
    "_version": 1,
    "result": "created",
    "_shards": {
        "total": 1,
        "successful": 1,
        "failed": 0
    },
    "_seq_no": 0,
    "_primary_term": 1
}

说明:非结构化的索引,不需要事先创建,直接插入数据默认创建索引

不指定id插入数据:

POST /haoke/user/
{
    "id":1002,
    "name":"张三",
    "age":20,
    "sex":"男"
}	
2.4.3 更新数据

在Elasticsearch中,文档数据是不可以修改的,但是可以通过覆盖的方式进行更新

PUT /haoke/user/1001
{
    "id":1001,
    "name":"张三",
    "age":21,
    "sex":"女"
}

更新后,版本_version字段会加1

局部更新:

#注意:这里多了_update标识
POST /haoke/user/1001/_update
{
    "doc":{
    	"age":23
    }
}
2.4.4 删除数据

发起DELETE请求

DELETE /haoke/user/1001

删除一个文档也不会立即从磁盘上移除,它只是被标记成已删除。Elasticsearch将会在你之后添加更多索引的时候才会在后台进行删除内容的清理

2.4.5 搜索数据
根据id搜索数据
GET /haoke/user/BbPe_WcB9cFOnF3uebvr
搜索全部数据
GET /haoke/user/_search
默认返回10条数据

7.x以后
GET /haoke/_search
关键字搜索数据
#查询年龄等于20的用户
GET /haoke/user/_search?q=age:20
2.4.6 DSL搜索

DSL查询(Query DSL),它允许你构建更加复杂、强大的查询

DSL(Domain Specific Language特定领域语言)以JSON请求体的形式出现

POST /haoke/user/_search
#请求体
{
    "query" : {
        "match" : { #match只是查询的一种
        	"age" : 20
        }
    }
}
实现:查询年龄大于30岁的男性用户
POST /haoke/user/_search
#请求数据
{
    "query": {
        "bool": {
            "filter": {
                "range": {
                    "age": {
                    	"gt": 30
                    }
                }
            },
            "must": {
                "match": {
                	"sex": "男"
                }
            }
        }
    }
}
全文检索
POST /haoke/user/_search
#请求数据
{
    "query": {
        "match": {
        	"name": "张三 李四"
        }
    }
}	
2.4.7 高亮显示
POST /haoke/user/_search
{
    "query": {
        "match": {
        	"name": "张三 李四"
        }
    },
    "highlight": {
        "fields": {
        	"name": {}
        }
    }
}
2.4.8 聚合

类似SQL中的group by操作

POST /haoke/user/_search
{
    "aggs": {
        "all_interests": {
            "terms": {
            	"field": "age"
            }
        }
    }
}

年龄30的有2条数据,20的有一条,40的一条

3 核心详解

3.1 文档

文档以JSON格式进行存储,可以是复杂的结构

{
    "_index": "haoke",
    "_type": "user",
    "_id": "1005",
    "_version": 1,
    "_score": 1,
    "_source": {
        "id": 1005,
        "name": "孙七",
        "age": 37,
        "sex": "女",
        "card": {
        	"card_number": "123456789"
        }
    }
}

其中,card是一个复杂对象,嵌套的Card对象

元数据 metadata

文档不只有数据,还包含元数据metadata–关于文档的信息。

三个必须的元数据节点:

  • _index 文档存储的地方
  • _type 文档代表的对象的类,7.x以后type只有_doc
  • _id 文档的唯一标识

_index

索引(index)类似于关系型数据库里的“数据库”——它是我们存储和索引关联数据的地方

物理空间上,数据被存储和索引在分片shards中,索引是把一个或多个分片分组在一起的逻辑空间。当然,java应用不用考虑分片,认为存储在索引中。

_type

使用相同类型(type)的文档表示相同的“事物”,因为他们的数据结构也是相同的,类似于java的类class

每个类型(type)都有自己的映射(mapping)或者结构定义,就像传统数据库表中的列一样。所有类型下的文档被存储在同一个索引下,但是类型的映射(mapping)会告诉Elasticsearch不同的文档如何被索引

_id

id和_index组合,在es中唯一标识一个文档,可自己定义id,也可es自动生成32位id。

3.2 查询响应

3.2.1 pretty

可以在查询url后面添加pretty参数,美化json格式

xxx/user/1005?pretty
3.2.2 指定响应字段

响应的数据中,如果不需要全部的字段,可以指定某些需要的字段进行返回

GET /haoke/user/1005?_source=id,name
#响应
{
    "_index": "haoke",
    "_type": "user",
    "_id": "1005",
    "_version": 1,
    "found": true,
    "_source": {
        "name": "孙七",
        "id": 1005
    }
}

如果不需要返回元数据

GET /haoke/user/1005/_source
或
GET /haoke/user/1005/_source?_source=id,name

3.3 判断文档是否存在

只需要判断文档是否存在,而不是查询文档内容,那么可以这样

HEAD /haoke/user/1005

只返回status是200还是404,表示查询的那一刻文档不存在

3.4 批量操作

3.4.1 批量查询
POST /haoke/user/_mget
{
	"ids" : [ "1001", "1003" ]
}

如果,某一条数据不存在,不影响整体响应,需要通过found的值进行判断是否查询到数据

3.4.2 _bulk操作

支持批量的插入、修改、删除操作,都是通过_bulk的api完成的

格式:

{ action: { metadata }}\n
{ request body }\n
{ action: { metadata }}\n
{ request body }\n
...

批量插入

{"create":{"_index":"haoke","_type":"user","_id":2001}}
{"id":2001,"name":"name1","age": 20,"sex": "男"}
{"create":{"_index":"haoke","_type":"user","_id":2002}}
{"id":2002,"name":"name2","age": 20,"sex": "男"}
{"create":{"_index":"haoke","_type":"user","_id":2003}}
{"id":2003,"name":"name3","age": 20,"sex": "男"}

最后一行需要有个回车

批量删除

{"delete":{"_index":"haoke","_type":"user","_id":2001}}
{"delete":{"_index":"haoke","_type":"user","_id":2002}}
{"delete":{"_index":"haoke","_type":"user","_id":2003}}

一次请求多少个性能最高?

最佳点sweetspot需要测试,开始数量可以在1000-5000个文档之间,一个好的批次最好在5-15MB大小。

3.5 分页

和SQL使用 LIMIT 关键字返回只有一页的结果一样,Elasticsearch接受fromsize 参数

size: 结果数,默认10
from: 跳过开始的结果数,默认0

如果你想每页显示5个结果,页码从1到3:

GET /_search?size=5
GET /_search?size=5&from=5
GET /_search?size=5&from=10

需要当心分页太深或一次请求过多的情况,因为结果返回之前会排序。

3.6 映射

有些时候我们是需要进行明确字段类型的,否则,自动判断的类型和实际需求是不相符的

从ElasticSearch 5.x开始不再支持string,由text和keyword类型替代

  • text类型,字段要被全文搜索,如email内容、产品描述。字段会被分词。text类型不用于排序,很少用于聚合
  • keyword类型,适用于索引结构化的字段,如email地址、主机名、状态码和标签。如字段需要过滤(如查询status为true的)、排序、聚合。keyword只能通过精确值查询到。
PUT /school
{
    "settings": {
        "index": {
        "number_of_shards": "2",
        "number_of_replicas": "0"
        }
    },
    "mappings": {
        "person": { # 7.x以后需要把person这个type删除
                "properties": {
                    "name": {
                    	"type": "text"
                    },
                    "age": {
                    	"type": "integer"
                    },
                    "mail": {
                    	"type": "keyword"
                    },
                    "hobby": {
                    	"type": "text"
                    }
            }
        }
    }
}

查看映射

GET /school/_mapping

3.7 结构化查询

3.7.1 term查询

term 主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串(未经分析的文本数据类型)

POST /school/person/_search
{
    "query" : {
        "term" : {
        	"age" : 20
        }
    }
}
3.7.2 terms查询

terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配

{
    "terms": {
    	"tag": [ "search", "full_text", "nosql" ]
    }
}

eg.

POST /itcast/person/_search
{
    "query" : {
        "terms" : {
        	"age" : [20,21]
        }
    }
}
3.7.3 range查询

按照指定范围查找一批数据:

{
    "range": {
    "age": {
            "gte": 20,
            "lt": 30
        }
    }
}
3.7.4 exists查询

查找文档中是否包含指定字段或没有某个字段

POST /haoke/user/_search
{
    "query": {
        "exists": { #必须包含
        	"field": "card"
        }
    }
}
3.7.5 match查询

会在真正查询之前用分析器先分析 match 一下查询字符

{
    "match": {
    	"tweet": "Leehom"
    }
}	
3.7.6 bool查询

合并多个条件查询结果,包含操作符

  • must 多个查询条件的完全匹配 类似&
  • must not 多个查询条件的相反匹配,类似!
  • should 至少有一个 类似or
{
    "bool": {
        "must": { "term": { "folder": "inbox" }},
        "must_not": { "term": { "tag": "spam" }},
        "should": [
            { "term": { "starred": true }},
            { "term": { "unread": true }}
        ]
    }
}

3.8 过滤查询

如,查询年龄20的用户

POST /itcast/person/_search
{
    "query": {
        "bool": {
            "filter": {
                "term": {
                    "age": 20
                }
           }
        }
    }
}

查询和过滤的对比

  • 过滤语句会询问每个文档的字段值是否包含着特定值
  • 查询语句会询问每个文档的字段值与特定值的匹配程度如何,给出一个相关性评分 _score,并且 按照相关性对匹
    配到的文档进行排序
  • 做精确匹配搜索时,最好用过滤语句,因为过滤语句可以缓存数据

4 中文分词

4.1 分词

分词就是指将一个文本转化成一系列单词的过程,也叫文本分析,在Elasticsearch中称之为Analysis,如我是中国人 --> 我/是/中国人

4.2 分词API

指定分词器进行分词

POST /_analyze
{
    "analyzer":"standard",
    "text":"hello world"
}	

指定索引分词

POST /itcast/_analyze
{
    "analyzer": "standard",
    "field": "hobby",
    "text": "听音乐"
}

4.3 中文分词

推荐IK分词器,算法是正向迭代最细粒度切分算法。

IK分词器 Elasticsearch插件地址:https://github.com/medcl/elasticsearch-analysis-ik

cd plugins;
wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.2.0/elasticsearch-analysis-ik-7.2.0.zip;
mkdir ik;cd ik;
unzip ../elasticsearch-analysis-ik-6.5.4.zip 
# 重启
./bin/elasticsearch

测试

POST /_analyze
{
    "analyzer": "ik_max_word",
    "text": "我是中国人"
}

5 全文搜索

全文搜索两个最重要的方面是:

  • 相关性(Relevance) 它是评价查询与其结果间的相关程度,并根据这种相关程度对结果排名的一种能力,这
    种计算方式可以是 TF/IDF 方法、地理位置邻近、模糊相似,或其他的某些算法。
  • 分词(Analysis) 它是将文本块转换为有区别的、规范化的 token 的一个过程,目的是为了创建倒排索引以及
    查询倒排索引

5.1 单词搜索

POST /itcast/person/_search
{
    "query":{
        "match":{
        	"hobby":"音乐"
        }
    },
    "highlight": {
        "fields": {
        	"hobby": {}
        }
    }
}

内部执行过程:

  1. 检查字段类型 hobby 字段是一个 text 类型( 指定了IK分词器),这意味着查询字符串本身也应该被分词
  2. 分析查询字符串 将查询的字符串 “音乐” 传入IK分词器中,输出的结果是单个项 音乐。因为只有一个单词项,所以 match 查询执行的是单个底层 term 查询
  3. 查找匹配文档 用 term 查询在倒排索引中查找 “音乐” 然后获取一组包含该项的文档
  4. 为每个文档评分 用 term 查询计算每个文档相关度评分 _score ,这是种将 词频(term frequency,即词 “音乐” 在相关文档的hobby 字段中出现的频率)和 反向文档频率(inverse document frequency,即词 “音乐” 在所有文档的hobby 字段中出现的频率),以及字段的长度(即字段越短相关度越高)相结合的计算方式

5.2 多词搜索

将match的hobby改为 "hobby":"音乐 篮球"

如果想搜索的是既包含“音乐”又包含“篮球”的用户,可指定词之间的逻辑关系

"match":{
    "hobby":{
        "query":"音乐 篮球",
        "operator":"and"
    }
}

如果要符合一定的相似度就可以查询到数据,在Elasticsearch中也支持这样的查询,通过minimum_should_match来指定匹配度,如:70%

"match":{
    "hobby":{
        "query":"游泳 羽毛球",
        "minimum_should_match":"80%"
    }
}

具体相似度需要结合业务需求反复测试。

5.4 组合搜索

在搜索时,也可以使用过滤器中讲过的bool组合查询,示例

"query":{
    "bool":{
        "must":{
            "match":{
            	"hobby":"篮球"
            }
        },
        "must_not":{
            "match":{
            	"hobby":"音乐"
            }
        },
        "should":[
            {
                "match": {
                	"hobby":"游泳"
                }
            }
        ]
    }
}

must_not 不影响评分,作用只是将不相关的文档排除。

5.5 权重

有些时候,我们可能需要对某些词增加权重来影响该条数据的得分

eg. 搜索关键字为“游泳篮球”,如果结果中包含了“音乐”权重为10,包含了“跑步”权重为2

"query": {
    "bool": {
        "must": {
            "match": {
                "hobby": {
                    "query": "游泳篮球",
                    "operator": "and"
                }
            }
        },
        "should": [
            {
                "match": {
                    "hobby": {
                        "query": "音乐",
                        "boost": 10
                    }
                }
            },
            {
                "match": {
                    "hobby": {
                        "query": "跑步",
                        "boost": 2
                    }
                }
            }
        ]
    }
}

6 es集群

6.1 集群节点

ELasticsearch的集群是由多个节点组成的,通过cluster.name设置集群名称,并且用于区分其它的集群,每个节点通过node.name指定节点的名称

节点类型:

master节点

  • 配置文件中node.master属性为true(默认为true),就有资格被选为master节点
  • master节点用于控制整个集群的操作。比如创建或删除索引,管理其它非master节点等

data节点

  • 配置文件中node.data属性为true(默认为true),就有资格被设置成data节点
  • data节点主要用于执行数据相关的操作。比如文档的CRUD

客户端节点

  • 配置文件中node.master属性和node.data属性均为false
  • 可以作为客户端节点,用于响应用户的请求,把请求转发到其他节点

部落节点

  • 当一个节点配置tribe.*的时候,它是一个特殊的客户端,它可以连接多个集群,在所有连接的集群上执行搜索和其他操作

6.2 搭建集群

# 3个虚拟机,分别部署安装es
mkdir /home/es-cluster
cp -R /home/es /home/es-cluster
elasticsearch.yml的配置修改如下面的文件,node02设置为master节点,node03设置为普通数据节点。

具体的elasticsearch.yml文件

cluster.name: es-itcast-cluster
node.name: node01
node.master: true
node.data: true
network.host: 192.168.200.207
http.port: 9200
discovery.zen.ping.unicast.hosts: ["192.168.200.207","192.168.200.208","192.168.200.209"]
discovery.zen.minimum_master_nodes: 2
http.cors.enabled: true
http.cors.allow-origin: "*"
cluster.initial_master_nodes: ["192.168.200.207","192.168.200.208"]

查看集群状态:_cluster/health

返回状态为green表示正常。

6.3 分片和副本

  • 一个分片(shard)是一个最小级别“工作单元(worker unit)”,它只是保存了索引中所有数据的一部分
  • 分片就是一个Lucene实例,并且它本身就是一个完整的搜索引擎。应用程序不会和它直接通信
  • 分片可以是主分片(primary shard)或者是复制分片(replica shard)
  • 索引中的每个文档属于一个单独的主分片,所以主分片的数量决定了索引最多能存储多少数据
  • 复制分片只是主分片的一个副本,它可以防止硬件故障导致的数据丢失,同时可以提供读请求
  • 当索引创建完成的时候,主分片的数量就固定了,但是复制分片的数量可以随时调整

6.4 故障转移

停掉node01,elasticsearch-header中cluster状态变黄,过一会会自动变绿。

将node01再启动,恢复后会重新加入cluster,重新分配节点信息。

说明:如果在配置文件中discovery.zen.minimum_master_nodes设置的不是N/2+1时,会出现脑裂问题,因此建议3个主机的,设置2个master;5个主机的,设置3个master

6.5 分布式文档

6.5.1 路由

当我们想一个集群保存文档时,文档该存储到哪个节点呢? 是随机吗? 是轮询吗?

实际有个计算公式,决定存储节点:

shard = hash(routing) % number_of_primary_shards

routing值默认是_id ,hash后,除以主分片数得到余数,余数的范围是0到主分片数之间,该值就是该文档所在的分片。

6.5.2 文档的写操作

新建、索引和删除请求都是写(write)操作,它们必须在主分片上成功完成才能复制到相关的副本分片上

elasticsearch学习和实践01_第2张图片

步骤:

  1. client给node01发新建、索引或删除的请求
  2. 根据文档的_id计算文档属于分片0,转发请求到node03,分片0的主分片位于该节点
  3. node03在主分片上执行请求,如果成功,转发请求到node01和node02的副本分片上。node03收到成功的返回后,再给client发送请求。
6.5.3 搜索文档(单个文档)

elasticsearch学习和实践01_第3张图片

步骤:

  1. client给node01发get请求
  2. 根据文档的_id确定文档属于分片0,对应的副本分片在node01和node02都有,转发请求到node02.
  3. node02返回文档给node01,返回给client

对于读请求,为平衡负载,会为每个请求选择不同的分片。

可能一个被索引的文档存在于主分片,还没来得及同步到副本分片,副本分片会报告未找到,主分片成功返回文档。索引请求成功返回给client后,文档在primary和replica分片都可用。

6.5.4 全文搜索

文档分散在各个节点,分布式情况下,如何搜索?分两个阶段:搜索query+取回fetch

搜索query

elasticsearch学习和实践01_第4张图片

查询阶段分三步:

  1. client发送search请求给node03,node03创建长度为from+size的空优先队列
  2. node03转发搜索请求到索引中每个分片的primary或replica,每个分片本地执行查询将结果放入大小为from+size的本地优先队列
  3. 每个分片返回document的id和优先队列的所有document的排序值给协调节点node03,node03取回后合并到自己的优先队列产生全局排序结果

取回fetch

elasticsearch学习和实践01_第5张图片

分发阶段的步骤:

  1. 协调节点分辨哪些document要取回,向相关分片发get请求
  2. 每个分片加载document并根据需要丰富enrich它们,再将document返回协调节点node03
  3. 所有document都被取回后,协调节点node03将结果返回client

7. java客户端

建议DSL查询,采用高阶客户端,后续续写这类代码

8. 生产配置

1. stop命令

#!/bin/sh

ps -ef | grep es | grep java | grep `whoami` | grep -v grep | awk '{print $2}' | while read pid
do
    kill -9 ${pid} 2>&1 >/dev/null
    echo "process id:${pid} shutdown successful!"
done

2. elasticsearch.yml

  • 适当增大写入buffer和bulk队列长度,提高写入性能和稳定性 indices.memory.index_buffer_size: 30% (默认10%)

9. 调优

首先是jdk调优

写优化

  1. 尽可能多的批量写,bulk API
  2. 减少refresh到磁盘的频率,index.refresh_interval:30s
  3. 增大flush的设置,默认512MB
  4. 减少副本数 大批量写的时候,先暂停副本复制,写入完成再复制

读优化

  1. 打分流程较耗资源,不需要可屏蔽 filter score=0

系统

  1. 内存:系统的50%用于es
  2. 磁盘:最好SSD

参考

  1. 博学谷elasticsearch课程
  2. Elasticsearch 移除 type 之后的新姿势
  3. es中文社区的其他帖子

你可能感兴趣的:(中间件,elasticsearch)