0%

elasticsearch(一)-基本概念

基本概念

ES是基于Lucene分布式搜索服务,可以存储整个对象或文档,分布式的实时文件存储,每个字段都被索引并可被搜索,分布式的实时分析搜索引擎,可以扩展到上百台服务器,处理PB级结构化或非结构化数据。

与传统数据库的对比

索引(index)

索引是ES的一个逻辑存储,对应关系型数据库中的库,ES可以把索引数据存放到服务器中,也可以sharding(分片)后存储到多台服务器上。每个索引有一个或多个分片,每个分片可以有多个副本。

类型(type)

ES中,一个索引可以存储多个用于不同用途的对象,可以通过类型来区分索引中的不同对象,对应关系型数据库中表的概念。但是在ES6.0开始,类型的概念被废弃,ES7中将它完全删除。删除type的原因:

我们一直认为ES中的“index”类似于关系型数据库的“database”,而“type”相当于一个数据表。ES的开发者们认为这是一个糟糕的认识。例如:关系型数据库中两个数据表示是独立的,即使他们里面有相同名称的列也不影响使用,但ES中不是这样的。

我们都知道elasticsearch是基于Lucene开发的搜索引擎,而ES中不同type下名称相同的filed最终在Lucene中的处理方式是一样的。举个例子,两个不同type下的两个user_name,在ES同一个索引下其实被认为是同一个filed,你必须在两个不同的type中定义相同的filed映射。否则,不同type中的相同字段名称就会在处理中出现冲突的情况,导致Lucene处理效率下降。

去掉type能够使数据存储在独立的index中,这样即使有相同的字段名称也不会出现冲突,就像ElasticSearch出现的第一句话一样“你知道的,为了搜索····”,去掉type就是为了提高ES处理数据的效率。

除此之外,在同一个索引的不同type下存储字段数不一样的实体会导致存储中出现稀疏数据,影响Lucene压缩文档的能力,导致ES查询效率的降低。

文档(document)

存储在ES中的主要实体叫文档,可以理解为关系型数据库中表的一行数据记录。每个文档由多个字段(field)组成。区别于关系型数据库的是,ES是一个非结构化的数据库,每个文档可以有不同的字段,并且有一个唯一标识。

映射(mapping)

mapping是对索引库中的索引字段及其数据类型进行定义,类似于关系型数据库中的表结构。ES默认动态创建索引和索引类型的mapping,这就像是关系型数据中的,无需定义表机构,更不用指定字段的数据类型。当然也可以手动指定mapping类型。

ES核心概念

分片(shard)

如果我们的索引数据量很大,超过硬件存放单个文件的限制,就会影响查询请求的速度,Es引入了分片技术。一个分片本身就是一个完成的搜索引擎,文档存储在分片中,而分片会被分配到集群中的各个节点中,随着集群的扩大和缩小,ES会自动的将分片在节点之间进行迁移,以保证集群能保持一种平衡。分片有以下特点:

  1. ES的一个索引可以包含多个分片(shard);
  2. 每一个分片(shard)都是一个最小的工作单元,承载部分数据;
  3. 每个shard都是一个lucene实例,有完整的简历索引和处理请求的能力;
  4. 增减节点时,shard会自动在nodes中负载均衡;
  5. 一个文档只能完整的存放在一个shard上(主节点)
  6. 一个索引中含有shard的数量,默认值为5,在索引创建后这个值是不能被更改的。
  7. 优点:水平分割和扩展我们存放的内容索引;分发和并行跨碎片操作提高性能/吞吐量;
  8. 每一个shard关联的副本分片(replica shard)的数量,默认值为1,这个设置在任何时候都可以修改。
  9. primary shard和对应的replica shard不能同时存在于同一个节点,所以最低的可用配置是两个节点,互为主备。
  10. primary shard是可读可写的,而replica shard是只读的。
1
2
3
4
5
分片的好处:
1.当某一台服务器宕机,可以保证其他数据的完整性(非最优方案)
2.横向扩容:当数据量增大时,只需要添加一个新的结点,然后创建新的索引,操作非常简单
3.看似占用了更多的服务器资源,实际上replica shard带来了性能和集群吞吐量的提升,这点和横向扩容是相同的。
不同的是,横向扩容是可以承载更多的数据,而replica shard是单纯的增加数据的副本,带来的是性能和高可用。

副本(replica)

副本(replica shard)就是shard的冗余备份,它的主要作用:

  1. 冗余备份,防止数据丢失;
  2. shard异常时负责容错和负载均衡;

ES的特性

分布式、高性能、高可用、可伸缩、易维护、速度快、弹性、灵活、操作简单、多语言客户端、X-Pack、hadoop/spark强强联手、开箱即用。

  • 分布式:横向扩展非常灵活
  • 全文检索:基于lucene的强大的全文检索能力;
  • 近实时搜索和分析:数据进入ES,可达到近实时搜索,还可进行聚合分析
  • 高可用:容错机制,自动发现新的或失败的节点,重组和重新平衡数据
  • 模式自由:ES的动态mapping机制可以自动检测数据的结构和类型,创建索引并使数据可搜索。
  • RESTful API:JSON + HTTP

应用领域:

1
2
3
4
5
1.百度(全文检索、高亮、搜索推荐)
2.各大网站的用户行为日志(用户点击、浏览、收藏、评论)
3.BI(Business Intelligence商业智能),数据分析:数据挖掘统计。
4.Github:代码托管平台,几千亿行代码
5.ELK:Elasticsearch(数据存储)、Logstash(日志采集)、Kibana(可视化)

优点

1
2
3
4
5
6
7
1.面向开发者友好,屏蔽了Lucene的复杂特性,集群自动发现(cluster discovery)
2.自动维护数据在多个节点上的建立
3.会帮我做搜索请求的负载均衡
4.自动维护冗余副本,保证了部分节点宕机的情况下仍然不会有任何数据丢失
5.ES基于Lucene提供了很多高级功能:复合查询、聚合分析、基于地理位置等。
6.对于大公司,可以构建几百台服务器的大型分布式集群,处理PB级别数据;对于小公司,开箱即用,门槛低上手简单。
7.相遇传统数据库,提供了全文检索,同义词处理(美丽的cls>漂亮的cls),相关度排名。聚合分析以及海量数据的近实时(NTR)处理,这些传统数据库完全做不到。

倒排索引

倒排索引(Inverted Index)也叫反向索引,有反向索引必有正向索引。通俗地来讲,正向索引是通过key找value,反向索引则是通过value找key。

1
2
3
4
5
6
7
数据结构:
1、包含这个关键词的document list
2、关键词在每个doc中出现的次数 TF term frequency
3、关键词在整个索引中出现的次数 IDF inverse doc frequency
4、关键词在当前doc中出现的次数
5、每个doc的长度,越长相关度越低
6、包含这个关键词的所有doc的平均长度

Term(单词):一段文本经过分析器分析以后就会输出一串单词,这一个一个的就叫做Term(直译为:单词)

Term Dictionary(单词字典):顾名思义,它里面维护的是Term,可以理解为Term的集合

Term Index(单词索引):为了更快的找到某个单词,我们为单词建立索引

Posting List(倒排列表):倒排列表记录了出现过某个单词的所有文档的文档列表及单词在该文档中出现的位置信息,每条记录称为一个倒排项(Posting)。根据倒排列表,即可获知哪些文档包含某个单词。(PS:实际的倒排列表中并不只是存了文档ID这么简单,还有一些其它的信息,比如:词频(Term出现的次数)、偏移量(offset)等,可以想象成是Python中的元组,或者Java中的对象)

(PS:如果类比现代汉语词典的话,那么Term就相当于词语,Term Dictionary相当于汉语词典本身,Term Index相当于词典的目录索引)

每个文档都有一个ID,如果插入的时候没有指定的话,Elasticsearch会自动生成一个。

es

高可用

ES在分配单个索引的分片时会将每个分片尽可能分配到更多的节点上。但是,实际情况取决于集群拥有的分片和索引的数量以及它们的大小,不一定总是能均匀地分布。

ES不允许Primary和它的Replica放在同一个节点中,并且同一个节点不接受完全相同的两个Replica

同一个节点允许多个索引的分片同时存在。

容错机制

在局部出错异常的情况下,保证服务正常运行并且有自行恢复能力。

Master节点会尝试重启故障机,故障机启动后将作为Slave节点

数据同步,Master会将宕机期间丢失的数据增量同步到重启机器对应的分片上去。

主节点的Shard分片和副本shard分片不能同时存在于同一个节点,横向扩容新节点时,ES会自动进行分片重新均衡。

如何提高ES分布式系统的可用性以及性能最大化?

(1)每台节点的Shard数量越少,每个shard分配的CPU、内存和IO资源越多,单个Shard的性能越好,当一台机器一个Shard时,单个Shard性能最好。

(2)稳定的Master节点对于群集健康非常重要!理论上讲,应该尽可能的减轻Master节点的压力,分片数量越多,Master节点维护管理shard的任务越重,并且节点可能就要承担更多的数据转发任务,可增加“仅协调”节点来缓解Master节点和Data节点的压力,但是在集群中添加过多的仅协调节点会增加整个集群的负担,因为选择的主节点必须等待每个节点的集群状态更新确认。

(3)反过来说,如果相同资源分配相同的前提下,shard数量越少,单个shard的体积越大,查询性能越低,速度越慢,这个取舍应根据实际集群状况和结合应用场景等因素综合考虑。

(4)数据节点和Master节点一定要分开,集群规模越大,这样做的意义也就越大。

(5)数据节点处理与数据相关的操作,例如CRUD,搜索和聚合。这些操作是I / O,内存和CPU密集型的,所以他们需要更高配置的服务器以及更高的带宽,并且集群的性能冗余非常重要。

(6)由于仅投票节不参与Master竞选,所以和真正的Master节点相比,它需要的内存和CPU较少。但是,所有候选节点以及仅投票节点都可能是数据节点,所以他们都需要快速稳定低延迟的网络。

(7)高可用性(HA)群集至少需要三个主节点,其中至少两个不是仅投票节点。即使其中一个节点发生故障,这样的群集也将能够选举一个主节点。生产环境最好设置3台仅Master候选节点(node.master = true node.data = true)

(8)为确保群集仍然可用,集群不能同时停止投票配置中的一半或更多节点。只要有一半以上的投票节点可用,群集仍可以正常工作。这意味着,如果存在三个或四个主节点合格的节点,则群集可以容忍其中一个节点不可用。如果有两个或更少的主机资格节点,则它们必须都保持可用

Master选举

每个节点都会不定期的在集群做广播,ping所有节点

es

es

如果是偶数节点,Elasticsearch会将其中一个排除在投票配置之外,确保其大小为奇数。

安装

elasticsearch

下载地址 ES的启动需要JDK环境

1
2
3
4
5
6
7
8
window版本启动:
elasticsearch.bat

linux版本启动:
./elasticsearch -d

验证:
http://localhost:9200/

Kibana

Kibana 是一个免费且开放的用户界面,能够让您对 Elasticsearch 数据进行可视化,可以进行各种操作,从跟踪查询负载,到理解请求如何流经整个应用,都能轻松完成。

下载地址

1
2
3
4
5
6
7
8
LINUX启动:
./kibana

WINDOW启动
kibana.bat

验证:
http://localhost:5601

Head插件

提供可视化的操作页面对ElasticSearch搜索引擎进行各种设置和数据检索功能,可以很直观的查看集群的健康状况,索引分配情况,还可以管理索引和集群以及提供方便快捷的搜索功能等等。

依赖于node 和 grunt管理工具 下载地址

1
2
3
4
安装grunt环境:
npm install -g grunt-cli
检查:
grunt -version

解压下载的压缩包,打开glasticsearch-head-master文件夹,修改Gruntfile.js文件,添加hostname:'*'

es

在当前目录输入npm installnpm run start启动

验证:http://localhost:9100/ 安装成功

如果无法发现ES节点,尝试在ES配置文件中设置允许跨域

1
2
3
http.cors.enabled: true

http.cors.allow-origin: "*"

ES节点

Master:主节点

每个集群都有且只有一个,尽量避免Master节点中配置node.data = true; Master节点的主要职责是和集群操作相关的内容,例如创建或删除索引、跟踪哪些节点是集群的一部分,并决定哪些分片分配给相关的节点。

voting:投票节点

需配置 Node.voting_only = true(仅投票节点,即使配置了node.master = true,也不会参选, 但是仍然可以作为数据节点)

coordinating:协调节点

每一个节点都隐式的是一个协调节点,如果同时设置了node.master = false和node.data=false,那么此节点将成为仅协调节点,该节点只能处理路由请求,处理搜索,分发索引操作

Master-eligible node:候选节点

设置node.master = true即是候选节点,具备竞选master的资格。

Data node:数据节点

数据节点主要是存储索引数据的节点,主要对文档进行增删改查操作,聚合操作等。

Ingest node:预处理节点

可以在实际的 indexing(索引)发生之前使用 ingest node 来预处理 documents(文档)通过node.ingest: true设置

Machine learning node:机器学习节点

相关配置参数如下:

1
2
3
4
5
6
7
8
9
10
11
12
1.node.master = true	 node.data = true
这是ES节点默认配置,既作为候选节点又作为数据节点,这样的节点一旦被选举为Master,压力是比较大的
通常来说Master节点应该只承担较为轻量级的任务,比如创建删除索引,分片均衡等。

2.node.master = true node.data = false
只作为候选节点,不作为数据节点,可参选Master节点,当选后成为真正的Master节点。

3.node.master = false node.data = false
既不当候选节点,也不作为数据节点,那就是仅协调节点,负责负载均衡

4.node.master=false node.data=true
不作为候选节点,但是作为数据节点,这样的节点主要负责数据存储和查询服务。

健康检查

1
2
3
URL:
_cat/health
_cluster/health

健康值状态

Green:所有Primary shard和Replica shard均为active,集群健康

Yellow:至少一个Replica shard不可用,但是所有Primary shard均为active,数据仍然是可以保证完整性的。

Red:至少有一个Primary shard为不可用状态,数据不完整,集群不可用。

集群配置

elasticearch.yml配置

1
2
3
4
#配置文件配置相同的集群名称
cluster.name: my-application
#各个节点需要有不同的结点名称
node.name: node-1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# ======================== Elasticsearch Configuration =========================
#
# NOTE: Elasticsearch comes with reasonable defaults for most settings.
# Before you set out to tweak and tune the configuration, make sure you
# understand what are you trying to accomplish and the consequences.
#
# The primary way of configuring a node is via this file. This template lists
# the most important settings you may want to configure for a production cluster.
#
# Please consult the documentation for further information on configuration options:
# https://www.elastic.co/guide/en/elasticsearch/reference/index.html
#
# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
#集群名字 同一个集群的节点要设置在同一个集群名称
cluster.name: csdemo
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
#节点名字 同一集群的节点名称不能相同
node.name: node-1
#
# Add custom attributes to the node:
#指定节点的部落属性,这是一个比集群更大的范围。
#node.attr.rack: r1
#
# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
# 数据存放目录
#path.data: /path/to/data
#
# Path to log files:
#
#path.logs: /path/to/logs
# ----------------------------------- Memory -----------------------------------
#
# Lock the memory on startup:
#锁定物理内存地址,防止elasticsearch内存被交换出去,也就是避免es使用swap交换分区
bootstrap.memory_lock: true
#
# Make sure that the heap size is set to about half the memory available
# on the system and that the owner of the process is allowed to use this
# limit.
#当系统进行内存交换的时候,es的性能很差
# Elasticsearch performs poorly when the system is swapping the memory.
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#设置ip绑定
network.host: 127.0.0.1
#
# Set a custom port for HTTP:
#自定义端口号
http.port: 9202
transport.tcp.port: 9302
# 是否启用TCP保持活动状态,默认为true
network.tcp.keep_alive: true
#是否启用tcp无延迟,true为启用tcp不延迟,默认为false启用tcp延迟
network.tcp.no_delay: true
#设置是否压缩tcp传输时的数据,默认为false,不压缩。
transport.tcp.compress: true
#
# For more information, consult the network module documentation.
#
# --------------------------------- Discovery ----------------------------------
#设置成主服务
node.master: false
# 时候进行数据存贮
node.data: true
#集群节点列表
# Pass an initial list of hosts to perform discovery when this node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
#当进行Master时,有哪些节点能参与竞选(node.master: true的节点)
discovery.seed_hosts: ["127.0.0.1:9301", "127.0.0.1:9302", "127.0.0.1:9303"]
#
# Bootstrap the cluster using an initial set of master-eligible nodes:
#设置集群启动时竞选Master的节点列表
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]

#每个节点在选中的主节点的检查之间等待的时间。默认为1秒
cluster.fault_detection.leader_check.interval: 15s

#设置主节点等待每个集群状态完全更新后发布到所有节点的时间,默认为30秒
cluster.publish.timeout: 90s


#集群内同时启动的数据任务个数,默认是2个
#cluster.routing.allocation.cluster_concurrent_rebalance: 2
#
#添加或删除节点及负载均衡时并发恢复的线程个数,默认4个
#cluster.routing.allocation.node_concurrent_recoveries: 4


#
# For more information, consult the discovery and cluster formation module documentation.

# ---------------------------------- Gateway -----------------------------------
#
# Block initial recovery after a full cluster restart until N nodes are started:
#集群中的N个节点启动后,才允许进行数据恢复处理
gateway.recover_after_nodes: 3

gateway.expected_nodes: 3
#配置限制了单节点上可以开启的ES存储实例的个数
node.max_local_storage_nodes: 3
gateway.auto_import_dangling_indices: true

#
# For more information, consult the gateway module documentation.
#
# ---------------------------------- Various -----------------------------------
#
# Require explicit names when deleting indices:
#删除索引必须要索引名称
action.destructive_requires_name: true
#是否允许跨域
http.cors.enabled: true
#允许跨域访问 *代表所有
http.cors.allow-origin: "*"

#master 和 data 的四种组合
#1.master=true & data = true 生产环境不推荐使用
#2.master=true & data = false 生产环境推荐使用,master不进行数据存储
#3.master=false & data = true 备机存储数据
#4.master = false & data = false 充当协调节点,类似nginx

#标记该节点具备竞争master的资格
node.master: true
#该节点进行数据存储
node.data: true

#标记投票节点
Node.voting_only = true

切记,如果拷贝了单点程序做集群节点,一定要把原有的data数据清除,否则多分Master节点数据会导致集群搭建失败。

CRUD

ElasticSearch是基于Rest风格的操作

Rest风格是一种软件架构风格,而不是标准,它只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。

method url地址 描述
PUT ip:9200/索引名称/类型名称/文档id 创建文档(指定文档id)
POST ip:9200/索引名称/类型名称 创建文档(随机文档id)
POST ip:9200/索引名称/类型名称/文档id/_update 修改文档
DELETE ip:9200/索引名称/类型名称/文档id 删除文档
GET ip:9200/索引名称/类型名称/文档id 通过文档id查询文档
POST ip:9200/索引名称/类型名称/_search 查询所有数据
1
2
3
4
#创建索引  index是索引名称
PUT /index?pretty
#案例
PUT /product?pretty
1
2
#查询所有索引
GET _cat/indices?v
1
2
3
4
#删除索引  index是索引名称
DELETE /index?pretty
#案例
DELETE /product?pretty
1
2
3
4
5
6
7
8
9
10
11
12
13
14
//插入数据 /index/type/id   若无索引会自动创建,   type被弱化,统一使用 "_doc" 
PUT /index/type/id
{
"key" : "value"
}

//案例:
PUT /product/_doc/1
{
"name" : "xiaomi phone",
"desc" : "shouji zhong de zhandouji",
"price" : 3999,
"tags": [ "xingjiabi", "fashao", "buka" ]
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//更新数据---全量更新---再次执行插入数据即可
PUT /product/_doc/1
{
"name" : "xiaomi phone",
"desc" : "shouji zhong de zhandouji",
"price" : 13999,
"tags": [ "xingjiabi", "fashao", "buka" ]
}

//更新数据---增量更新
PUT /index/type/id/_update
{
"doc": {
"key" : "value"
}
}

//增量更新案例
PUT /product/_doc/1/_update
{
"doc": {
"price" : 3999
}
}
1
2
3
4
#删除数据
DELETE /index/type/id
#案例
DELETE /product/_doc/1