Elasticsearch是一个基于Lucene库的搜索引擎 ,提供分布式可扩展的实时搜索和分析引擎,一个建立在全文搜索殷勤Apache Lucene基础上的搜索引擎,它不仅可以进行全文搜索,还可以进行一下工作:
分布式实时文件存储,基于内存,可持久化,并将每一个字段都编入索引,使其可以被搜索,更加适用于企业内部数据的搜索
实时分析的分布式搜索引擎
可以扩展到上百台服务器,处理PB级别的结构化或非结构化数据
提供了REST API的操作接口,开箱即用
存储单位:
1KB=1024B
1MB=1024KB
1GB=1024MB
1TB=1024GB
1PB=1024TB
1EB=1024PB
1ZB=1024EB
1YB=1024ZB
基本概念
ElasticSearch是面向文档型数据库,一条数在这里就是一个文档
1.索引(Index)
索引是具有相似特性的文档集合。例如,可以为客户数据提供索引,为产品目录建立一个索引,以及为订单数据建立另一个索引。索引由名称(必须全部为小写)标识,该名称用于在对其中的文档执行索引、搜索、更新和删除操作时引用索引。在单个集群中,您可以定义尽可能多的索引。
2.文档(document)
Elasticsearch文档时一个存储在索引中的JSON文档,每个文档都有一个类型和对应的ID,这是唯一的。
如:
{
"_index" : "packtpub",
"_type" : "elk",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source":{
book_name : "learning elk",
book_author:"鲁迅"
}
}
3.字段(Field)
文档内的一个基本单位,键值对形式就是字段,键与键值组合起来就是一个字段
4.类型(Type)
类型是index下的一个逻辑分类。比如weather这个index里,可以按照城市分组,也可以按照气候分组,这种分组就叫做类型
5.映射(Mapping)
映射用于映射文档的每个field及其对应的数据类型,例如字符串、整数、浮点数、双精度数、日期等等。
6.分片(Shard)
shard:单台机器无法存储大量数据,es可以将一个索引中的数据切分为多个shard,分布在多台服务器上存储。有了shard就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能
分片原因:单节点故障以及读写性能的限制
7.主分片(Primary shard)与复制分片(Replica shard)
复制分片通常驻留在一个不同的节点上,在故障转移和负载均衡的情况下,可以满足多个请求。
分片也就是一个es的集群,本来一个300T的数据在一台es上进行存储,大量用户访问该服务器,访问量多后,存在了读写性能的限制,当然也存在,一旦服务器故障,就会导致数据的丢失。
所以将一个300TB的数据以分片的方式存储在三台服务器,以提高读写和数据安全性,三个不同的节点会选举一个作为master节点,master节点用来控制所有节点,而每个节点中会存在非本地节点的一个复制节点,以保证某台节点宕机后,数据不会丢失
8.分词
把一段文本中的词按一定规则进行切分
如:在百度引擎中搜索一句话时,结果可以是一整局话,也可能是一句话中的几个词语
9.集群(Cluster)
集群时存储索引数据的节点集合。Elasticsearch提供了水平的可伸缩性用以存储集群中的数据。每个集群都由一个集群名称来表示,不同的节点指明集群名称连接在一起
10.节点(Node)
节点是一个单独运行的Elasticsearch实例,他属于一个集群。默认情况下,Elasticsearch中的每个节点都加入名为“elasticsearch”的集群。每个节点都可以在elasticsearch中使用自己的elasticsearch.yml,它们可以对内存和资源分配有不同的设置
ES集群
集群节点分类
1.数据节点(Data Node)
数据节点索引文档并对索引执行搜索。建议添加更多的数据节点,以提高性能或扩展集群。通过elasticsearch中设置这些属性,可以使节点成为一个数据节点。elasticsearch.yml配置
node.master:是否有资格参选master
node.master: false
node.data: true
2.管理节点(Master Node)
主节点负责集群的管理。对于大型集群,建议有三个专用的主节点(一个主节点和两个备份节点),它们只作为主节点,不存储索引或执行搜索。在elasticsearch.yml配置声明节点为主节点:
node.master: true
node.data: false
3.路由节点也叫负载均衡节点(Routing Node/Load Balancer Node)
这些节点不扮演主或数据节点的角色,但只需执行负载均衡,或为搜索路由,或将文档编入适当的节点。这对于高容量搜索或索引操作非常有用。
node.master: false
node.data: false
4.提取节点(Ingest节点)
可以创建多个预处理管道,用以修改传入文档
Zendiscovery通信
默认ES进程会绑定在自己的回环地址上,然后扫描本机的9300-9305号端口,尝试跟其他端口上的启动的ES进程进行通信,然后自动形成一个集群。如果修改了监听地址为非回环地址,ES按照配置文件里指定的地址或自动扫描当前网段其他节点,自动根其他节点上的ES node进行通信
Master选举
选举过程每时每刻都在进行,如下图所示
脑裂
因为网络或者其他故障,导致一个集群被划分成了两个或者多个集群,这些集群都有多个node以及一个master,那么原来的集群就出现了多个master。master主宰了集群状态的维护以及shard的分配,因此如果有多个master,可能会导致数据被破坏
脑裂容错机制
- 集群状态
状态 | 释义 |
---|---|
green | 所有主分片和从分片都可用 |
yellow | 所有主分片可用,但存在不可用的从分片 |
red | 存在不可用的主分片 |
- 宕机瞬间
master node宕机的一瞬间,该节点的primary shard(主分片)就没有了,此时状态就不是active status,那么集群中就不是所有的主分片都是active了
- 容错步骤一
master选举,ES自动选举另一个node成为master,承担器master的责任
- 容错步骤二
新master将丢失掉的主分片的某个复制分区提升为主分片,此时cluster status会变成yellow,因为所有的主分片都变成active status了,但是少了一个复制分片
- 容错步骤三
master将缺失的复制分片复制到集群中某节点,此时所有主分片和复制分片都可用,集群状态变为green。将修复好的宕机节点重新加入集群,供master支配。
部署ES集群
集群环境
三台服务器都需要Java环境
192.168.1.1
192.168.1.4
192.168.1.5
实验步骤
安装Java
tar zxf jdk-8u201-linux-x64.tar.gz -C /usr/local/
mv /usr/local/jdk1.8.0_201/ /usr/local/java
echo "export JAVA_HOME=/usr/local/java
export JRE_HOME=/usr/local/java/jre
export CLASSPATH=$JAVA_HOME/lib:$JRE_HOME/lib
export PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin" >> /etc/profile
source /etc/profile
网络对时
ntpdate ntp.ntsc.ac.cn
关闭防火墙沙盒
systemctl stop firewalld
systemctl disable firewalld # 禁止开机自启
vim /etc/selinux/config
修改
SELINUX=disabled
调整系统参数了解
查看系统文件描述符,最大连接数
ulimit -n(默认为1024)
修改方法一(临时):
ulimit -HSn 2048
修改方法二(永久):
vim /security/limits.conf
添加:
* soft nproc 2048
* hard nproc 4096
通过修改配置文件的方法来调整系统参数
# 打开文件的软限制,ES要求系统文件描述符大于65535
echo "* soft nofile 655360" >> /etc/security/limits.conf
# 打开文件的硬限制
echo "* hard nofile 655360" >> /etc/security/limits.conf
# 用户可用进程数软限制
echo "* soft nproc 2048" >> /etc/security/limits.conf
# 用户可用进程数硬限制
echo "* hard nproc 4096" >> /etc/security/limits.conf
# JVM能够使用的最大线程数
echo "vm.max_map_count=655360" >> /etc/sysctl.conf
sysctl -p
vm.max_map_count = 655360
ES不可以使用root用户启动,否则报错
useradd es
创建ES相关目录,并安装
mkdir -p /es/{data,logs}
mkdir /usr/local/es/plugins/ik # 创建分词器插件目录,这个也要授权
tar zxf elasticsearch-6.3.2.tar.gz
mv elasticsearch-6.3.2 /usr/local/es
chown -R es:es /es /usr/local/es/
安装分词器插件
unzip elasticsearch-analysis-ik-6.3.2.zip -d /usr/local/es/plugins/ik
此时需要重启服务器,因为之前的修改参数需要重启来生效
以上步骤三台服务器都做
修改1.1主机es配置文件elasticsearch.yml
vim /usr/local/es/config/elasticsearch.yml
修改去注释
cluster.name: my-application # 集群名称17行,集群名必须都一样
node.name: node-1 # 当前节点名,要与之后的节点名区分
path.data: /es/data # 修改为刚才创建的目录
path.logs: /es/logs # 同上
network.host: 192.168.1.1 # 改为本机ip
http.port: 9200 # http访问端口
transport.tcp.port: 9300 # 集群通讯端口
# 集群中的主机通讯地址
discovery.zen.ping.unicast.hosts: ["192.168.1.1:9300", "192.168.1.4:9300", "192.168.1.5:9300"]
# 至少有2个选举资格的服务器才开始选举
discovery.zen.minimum_master_nodes: 2
# 集群重启后,有三个节点正常,就开始数据恢复
gateway.recover_after_nodes: 3
添加:
# 两个参数相对独立
node.data: true # 数据节点
node.master: true # 主节点选举资格
# 集群通讯超时时间,也可防止脑裂
discovery.zen.ping_timeout: 120s
# 等待3个节点的时间
gateway.recover_after_time: 5m
# 超过等待时间后,有2个节点,也可以恢复数据
gateway.recover_after_data_nodes: 2
使用scp将配置文件传给其他两台服务器
scp /usr/local/es/config/elasticsearch.yml 192.168.1.4:/usr/local/es/config/
scp /usr/local/es/config/elasticsearch.yml 192.168.1.5:/usr/local/es/config/
192.168.1.4
vim /usr/local/es/config/elasticsearch.yml
修改:
node.name: node-2
network.host: 192.168.1.4
192.168.1.5
vim /usr/local/es/config/elasticsearch.yml
修改:
node.name: node-3
network.host: 192.168.1.5
三台都启动
启动es服务之前,要确认/es目录和/usr/local/es两个目录的属主属组
su es
/usr/local/es/bin/elasticsearch # 阻塞即成功
192.168.1.1
[2020-02-29T19:02:08,574][INFO ][o.e.n.Node ] [node-1] started
192.168.1.4
[2020-02-29T11:03:10,601][INFO ][o.e.n.Node ] [node-2] started
192.168.1.5
[2020-02-29T11:03:12,119][INFO ][o.e.n.Node ] [node-3] started
出现以上三条之后,要等很长时间,5分钟以上,状态才会变成以下的green
分别访问每台主机的9200端口查看集群状态,green为成功,如果是red需要等待一段时间,3分钟左右
http://192.168.1.1:9200/_cluster/health?pretty
http://192.168.1.4:9200/_cluster/health?pretty
http://192.168.1.5:9200/_cluster/health?pretty
{
"cluster_name" : "my-application",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 3,
"active_primary_shards" : 0,
"active_shards" : 0,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 0,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 100.0
}
分词器插件的简单实用
192.168.1.1
创建索引(index)
# 使用put方式上传目录
curl -XPUT http://192.168.1.1:9200/chide?pretty
# 返回信息
{
"acknowledged":true,
"shards_acknowledged":true,
"index":"chide"
}
创建映射(mapping)
curl -XPOST -H 'Content-Type: application/json' http://192.168.1.1:9200/chide/shuiguo/_mapping?pretty -d'
{
"properties": {
"content": {
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "ik_max_word"
}
}
}'
# 返回信息
{"acknowledged":true}
添加数据
curl -XPOST -H 'Content-Type: application/json' http://192.168.1.1:9200/chide/shuiguo/1?pretty -d '{"content": "水果很好吃"}'
# 返回信息
{
"_index":"haochi",
"_type":"shuiguo",
"_id":"1","_version":1,
"result":"created",
"_shards":{"total":2,"successful":2,"failed":0},
"_seq_no":0,"_primary_term":1
}
使用分词器进行简单分词搜索操作
curl -XPOST -H 'Content-Type: application/json' http://192.168.1.1:9200/chide/shuiguo/_search?pretty -d'
{
"query": {"match": {"content": "好吃"}},
"highlight": {
"pre_tags": ["<tag1>","<tag2>"],
"post_tags": ["</tag1>","</tag2>"],
"fields": {
"content": {}
}
}
}'
# 返回信息
{
"took" : 111,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 0.2876821,
"hits" : [
{
"_index" : "chide",
"_type" : "shuiguo",
"_id" : "1",
"_score" : 0.2876821,
"_source" : {
"content" : "水果很好吃"
},
"highlight" : {
"content" : [
"水果很<tag1>好吃</tag1>"
]
}
}
]
}
}
ES常用命令
查看节点信息
http://192.168.1.1:9200
{
"name" : "node-1",
"cluster_name" : "my-application",
"cluster_uuid" : "VmGAFsA7TF6Qs9HlML-Ipg",
"version" : {
"number" : "6.3.2",
"build_flavor" : "default",
"build_type" : "tar",
"build_hash" : "053779d",
"build_date" : "2018-07-20T05:20:23.451332Z",
"build_snapshot" : false,
"lucene_version" : "7.3.1",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}
查看集群节点
http://192.168.1.1:9200/_cat/nodes
带*的即为master
192.168.1.1 18 96 1 0.00 0.01 0.05 mdi * node-1
192.168.1.5 9 92 1 0.01 0.02 0.05 mdi - node-3
192.168.1.4 13 96 1 0.01 0.02 0.05 mdi - node-2
查看集群master
http://192.168.1.1:9200/_cat/master
查看所有可查看选项
http://192.168.1.1:9200/_cat
=^.^=
/_cat/allocation
/_cat/shards
/_cat/shards/{index}
/_cat/master
/_cat/nodes
/_cat/tasks
/_cat/indices
/_cat/indices/{index}
/_cat/segments
/_cat/segments/{index}
/_cat/count
/_cat/count/{index}
/_cat/recovery
/_cat/recovery/{index}
/_cat/health
/_cat/pending_tasks
/_cat/aliases
/_cat/aliases/{alias}
/_cat/thread_pool
/_cat/thread_pool/{thread_pools}
/_cat/plugins
/_cat/fielddata
/_cat/fielddata/{fields}
/_cat/nodeattrs
/_cat/repositories
/_cat/snapshots/{repository}
/_cat/templates
显示master详细信息
http://192.168.1.1:9200/_cat/master?v
id host ip node
9DdbXyH-SfG5VmIdAhFBLQ 192.168.1.1 192.168.1.1 node-1
输出可用显示的列
http://192.168.1.1:9200/_cat/master?help
id | | node id
host | h | host name
ip | | ip address
node | n | node name
输出信息中指定的列
http://192.168.1.1:9200/_cat/master?h=ip,node
192.168.1.1 node-1
查看所有索引
http://192.168.1.1:9200/_cat/indices?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open chide -0fPWjUeTQa-a37rUN-gnA 5 1 1 0 8.2kb 4.1kb
green open haochi FqgMVqIQQvKFIzUDrGtBZA 5 1 1 0 9.1kb 4.5kb
green open shipin XZD6gXi2SP2UPN_XzuukUA 5 1 1 0 11.9kb 5.9kb
green open maiping 0ux7x0M-TWa78X1cRF8P6g 5 1 1 0 8.2kb 4.1kb
创建索引
curl -XPUT http://192.168.1.1:9200/pjf1?pretty
# 返回信息
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "pjf1"
}
关闭索引
curl -XPOST http://192.168.1.1:9200/pjf1/_close?pretty
# 返回信息
{
"acknowledged" : true
}
开启索引
curl -XPOST http://192.168.1.1:9200/pjf1/_open?pretty
# 返回信息
{
"acknowledged" : true,
"shards_acknowledged" : true
}
插入数据
curl -XPUT http://192.168.1.1:9200/pjf1/fulltext/1?pretty -H 'Content-Type: application/json' -d '
{
"name": "cyj"
}'
# 返回信息
{
"_index" : "pjf1",
"_type" : "fulltext",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 2
}
取出fulltext类型id为1的数据
curl -XGET 'http://192.168.1.1:9200/pjf1/fulltext/1?pretty'
# 返回信息
{
"_index" : "pjf1",
"_type" : "fulltext",
"_id" : "1",
"_version" : 1,
"found" : true,
"_source" : {
"name" : "cyj"
}
}
更新文档
curl -XPOST 'http://192.168.1.1:9200/pjf1/fulltext/1/_update?pretty' -H 'Content-Type:application/json' -d'
{
"doc": {"name": "mupei"}
}'
# 返回信息
{
"_index" : "pjf1",
"_type" : "fulltext",
"_id" : "1",
"_version" : 2,
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 2
}
删除id为1的数据()
curl -XDELETE 'http://192.168.1.1:9200/pjf1/fulltext/1?pretty'
{
"_index" : "pjf",
"_type" : "fulltext",
"_id" : "1",
"_version" : 3,
"result" : "deleted",
"_shards" : {
"total" : 2,
"successful" : 2,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1
}
查询符合条件的记录
curl -XPOST 'http://192.168.1.1:9200/pjf1/fulltext/_search?pretty' -H 'Content-Type:application/json' -d'
{
"query": {"match": {"name": "mupei"}}
}'
# 返回信息
{
"took" : 13,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : 1,
"max_score" : 0.2876821,
"hits" : [
{
"_index" : "pjf1",
"_type" : "fulltext",
"_id" : "1",
"_score" : 0.2876821,
"_source" : {
"name" : "mupei"
}
}
]
}
}
清空缓存
curl -XPOST 'http://192.168.1.1:9200/pjf1/_cache/clear?pretty' -H 'Content-Type:application/json'
# 返回信息
{
"_shards" : {
"total" : 10,
"successful" : 10,
"failed" : 0
}
}
flush和refresh(强制刷新数据到磁盘)
# flush
curl -XPOST 'http://192.168.1.1:9200/pjf1/_flush?pretty' -H 'Content-Type:application/json'
# 返回信息
{
"_shards" : {
"total" : 10,
"successful" : 10,
"failed" : 0
}
}
# refresh
curl -XPOST 'http://192.168.1.1:9200/pjf1/_refresh?pretty' -H 'Content-Type:application/json'
# 返回信息
{
"_shards" : {
"total" : 10,
"successful" : 10,
"failed" : 0
}
}
refresh与flush的区别
当一个文档进入ES的初期,文档是被存储到内存里的,默认经过1s之后,会被写入文件系统缓存,只有该文档就可以被搜索到了,注意,此时该索引数据被没有最终写入到磁盘上。如果你对这1s的时间间隔还不满意,调用_refresh就可以立即实现内存->文件系统缓存,从而使文档可以理解被搜索到。ES为了数据的安全,在接收写入文档的时候,在写入内存buffer的同时,会写一份translog日志,从而出现程序故障/磁盘异常时,保证数据的完整和安全。flush会触发lucene commit,并情况translog日志文件。translog的flush是ES在后台自动执行的,默认情况下ES每隔5s会去检测要不要flush translog,默认条件是:每30分钟主动进行一次flush,或者当translog文件大小大于512MB主动进行一次flush。
删除索引
curl -XDELETE http://192.168.1.1:9200/pjf1?pretty
# 返回信息
{
"acknowledged" : true
}
head插件的使用(集群图形化管理界面)
head插件是es集群的一个图形化管理
将三台集群全部进行以下操作
先将es集群停掉,注意用root用户执行以下操作,启动集群时在切换,或者换终端也可以
tar -zxf node-v10.6.0-linux-x64.tar.gz
mv node-v10.6.0-linux-x64 /usr/local/node
echo 'export PATH=$PATH:/usr/local/node/bin' >> /etc/profile
source /etc/profile
node -v
v10.6.0
npm -v
6.1.0
node.js中的npm是用来安装插件工具,类似于Python中的pip
安装head插件
unzip elasticsearch-head-master.zip
mv elasticsearch-head-master /usr/local/head
使用npm安装一下工具
1、cnpm:对head插件的源代码进行编译安装
2、grunt:管理head插件启动
cd /usr/local/head/
npm install -g cnpm --registry=https://registry.npm.taobao.org
npm install -g grunt --registry=https://registry.npm.taobao.org
使用cnpm编译安装head插件源代码
# 需要在head目录
cnpm install
# 如果出现红色的deprecate不是报错,只需要看最后一行的all packages installed
对grunt插件的配置文件修改
vim /usr/local/head/Gruntfile.js
# 92行的option下面添加一行:
# 表示所有人可以访问
hostname: '0.0.0.0',
修改ES的配置文件
vim /usr/local/es/config/elasticsearch.yml
# 在最后一行添加
http.cors.enabled: true # 允许跨域访问
http.cors.allow-origin: "*" # 允许跨域访问的所有ip访问
启动head插件
cd /usr/local/head
grunt server
(node:3467) ExperimentalWarning: The http2 module is an experimental API.
Running "connect:server" (connect) task
Waiting forever...
Started connect web server on http://localhost:9100
启动ES集群,至少5分钟才能成功启动
su es
/usr/local/es/bin/elasticsearch
启动成功后,访问图形化管理工具
访问网页http://192.168.1.1:9100/
连接es集群,图中的红圈处就是创建的索引信息
如图所示为分片情况,可以看到图中的01234为各节点的分片情况,可以看到有粗线框和细线框,细线框是复制分片所在节点,粗线框为主分片所在节点
也可以通过点击绿色方块,查看primary的值,true为主分片,false为复制分片
创建索引
查看文档
查询操作,可以结合es常用命令的操作来