1.1 目标人群
适用人员:使用过ES (elasticsearch), 对 ES 有初步的了解,想要深一步深入学习的人
知识点:以 ES 索引生命周期为知识点,这一个月查看文档的初步收集
1.es 结构初识。 2. es 基础知识 3.es索引生命周期使用
1.3 ES 结构初识
通过命令行写入数据并查看数据,了解 ES 和 MySQL 数据库是类似的,都是通过结构化来存储数据
#写入一条数据 PUT my_index1/_doc/1 { "name" : "bob", "age": 2 } #查看写入的数据 GET my_index1/_doc/1 #查看索引的设置 GET my_index1/_settings #查看索引的字段结构 GET my_index1/_mapping #查看索引,默认包含索引的设置和字段结构 GET my_index1 #查看所有的索引 GET _cat/indices
1.3.1 案例演示
#写入一条数据 PUT my_index1/_doc/1 { “name” : “bob” }
#查看写入的数据 GET my_index1/_doc/1
-
_index -文档所属的索引名
-
_type -文档所属的类型名
-
_id -文档唯一Id
-
_version :文档的版本信息
-
_source:文档的原始Json数据
-
_seq_no:
-
_primary_term:
-
found:
-
_all:整合所有字段内容到该字段,已被废除
elasticsearch乐观锁机制实现版本控制primary_term和seq_no
elasticsearch是采用乐观锁+version来解决并发问题
#查看索引的设置 GET my_index1/_settings
#查看索引的字段结构 GET my_index1/_mapping
#查看索引,默认包含索引的设置和字段结构 GET my_index1
#查看所有的索引 GET _cat/indices
2.1 相关概念解释
(1)Near Realtime(NRT):近实时,两个意思,从写入数据到数据可以被搜索到有一个小延迟(大概1秒);基于es执行搜索和分析可以达到秒级
(2)Cluster:集群,包含多个节点,每个节点属于哪个集群是通过一个配置(集群名称,默认是elasticsearch)来决定的,对于中小型应用来说,刚开始一个集群就一个节点很正常
(3)Node:节点(简单理解为集群中的一个服务器),集群中的一个节点,节点也有一个名称(默认是随机分配的),节点名称很重要(在执行运维管理操作的时候),默认节点会去加入一个名称为“elasticsearch”的集群,如果直接启动一堆节点,那么它们会自动组成一个elasticsearch集群,当然一个节点也可以组成一个elasticsearch集群
(4)Index:索引(简单理解就是一个数据库),包含一堆有相似结构的文档数据,比如可以有一个客户索引,商品分类索引,订单索引,索引有一个名称。一个index包含很多document,一个index就代表了一类类似的或者相同的document。比如说建立一个product index,商品索引,里面可能就存放了所有的商品数据,所有的商品document。
(5)Type:类型(简单理解就是一张表),每个索引里都可以有一个或多个type,type是index中的一个逻辑数据分类,一个type下的document,都有相同的field,比如博客系统,有一个索引,可以定义用户数据type,博客数据type,评论数据type。
(6)Document&field:文档(就是一行数据),es中的最小数据单元,一个document可以是一条客户数据,一条商品分类数据,一条订单数据,通常用JSON数据结构表示,每个index下的type中,都可以去存储多服务器托管个document。一个document里面有多个field,每个field就是一个数据字段。
(7)shard:单台机器无法存储大量数据,es可以将一个索引中的数据切分为多个shard,分布在多台服务器上存储。有了shard就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。每个shard都是一个lucene index。
(8)replica:任何一个服务器随时可能故障或宕机,此时shard可能就会丢失,因此可以为每个shard创建多个replica副本。replica可以在shard故障时提供备用服务,保证数据不丢失,多个replica还可以提升搜索操作的吞吐量和性能。primary shard(建立索引时一次设置,不能修改,默认5个),replica shard(随时修改数量,默认1个),默认每个索引10个shard,5个primary shard,5个replica shard,最小的高可用配置,是2台服务器。
(9)Segment: 每个segment本质上就是一个逆向索引。
2.3 ES 节点分类
主节点:负责集群层面的相关操作,管理集群变更。尽可能做少量的工作,生产环境应该尽量分离主节点和数据节点。
数据节点:负责保存数据、执行数据相关操作:CRUD、搜索、聚合等。对CPU、内存、IO要求较高。一般情况下,数据读写流程只和数据节点交互,不会和主节点打交道。
客户端节点(路由节点): 当主节点和数据节点配置都设置为false的时候,该节点只能处理路由请求,处理搜索,分发索引操作等,从本质上来说该客户节点表现为智能负载平衡器。独立的客户端节点在一个比较大的集群中是非常有用的,他协调主节点和数据节点,客户端节点加入集群可以得到集群的状态,根据集群的状态可以直接路由请求。
2.3.1 Master节点的特殊性
ES中有一项工作是Master独有的:维护集群状态。集群状态信息,只由Master节点进行维护,并且同步到集群中所有节点,其他节点只负责接收从Master同步过来的集群信息而没有维护的权利。集群状态包括以下信息:
-
集群层面的配置
-
集群内节点的管理
-
各索引的设置,映射,分析器和别名等
-
索引内各分片所在的节点位置
【思维拓展】ES集群中的每个节点都会存储集群状态,知道索引内各分片所在的节点位置,因此在整个集群中的任意节点都可以知道一条数据该往哪个节点分片上存储。反之也知道该去哪个分片读。所以,Elasticsearch不需要将读写请求发送到Master节点,任何节点都可以作为数据读写的切入点对请求进行响应。这样进一步减轻了Master节点的网络压力,同时提高了集群的整体路由性能。
2.4.1 写索引过程
ES 集群中每个节点通过路由都知道集群中的文档的存放位置,所以每个节点都有处理读写请求的能力。
在一个写请求被发送到某个节点后,该节点即为协调节点,协调节点会根据路由公式计算出需要写到哪个分片上,再将请求转发到该分片的主分片节点上。
shard = hash(routing) % number_of_primary_shards
routing 是一个可变值,默认是文档的 _id
,也可以设置成一个自定义的值。routing 通过 hash 函数生成一个数字,然后这个数字再除以 number_of_primary_shards
(主分片的数量)后得到余数 。这个在 0 到 numberofprimary_shards-1 之间的余数,就是我们所寻求的文档所在分片的位置。
假设 shard = hash(routing) % 4 = 0 ,则过程大致如下:
-
客户端向 ES1节点(协调节点)发送写请求,通过路由计算公式得到值为0,则当前数据应被写到主分片 S0 上。
-
ES1 节点将请求转发到 S0 主分片所在的节点 ES3,ES3 接受请求并写入到磁盘。
-
并发将数据复制到两个副本分片 R0 上,其中通过乐观并发控制数据的冲突。一旦所有的副本分片都报告成功,则节点 ES3 将向协调节点报告成功,协调节点向客户端报告成功。
2.4.2 写入数据底层原理
-
数据先写入到buffer里面,在buffer里面的数据时搜索不到的,同时将数据写入到translog日志文件之中
-
如果buffer快满了,或是一段时间之后(定时),就会将buffer数据refresh到一个新的OS cache之中,然后每隔1秒,就会将OS cache的数据写入到segment file之中,但是如果每一秒钟没有新的数据到buffer之中,就会创建一个新的空的segment file,只要buffer中的数据被refresh到OS cache之中,就代表这个数据可以被搜索到了。当然可以通过restful api ,手动的执行一次refresh操作,就是手动的将buffer中的数据刷入到OS cache之中,让数据立马搜索到,只要数据被输入到OS cache之中,buffer的内容就会被清空了。
但是此时segment是放在缓存中的,并没有落入磁盘,此时新创建的segment是可以进行搜索的。
同时进行的是,数据到shard之后,就会将数据写入到translog之中,每隔5秒将translog之中的数据持久化到磁盘之中
-
重复以上的操作,每次一条数据写入buffer,同时会写入一条日志到translog日志文件之中去,这个translog文件会不断的变大,当达到一定的程度之后,就会触发commit操作。
-
将一个commit point写入到磁盘文件,里面标识着这个commit point 对应的所有segment file
-
强行将OS cache 之中的数据都fsync到磁盘文件中去。
解释:translog的作用:在执行commit之前,所有的而数据都是停留在buffer或OS cache之中,无论buffer或OS cache都是内存,一旦这台机器死了,内存的数据就会丢失,所以需要将数据对应的操作写入一个专门的日志问价之中,一旦机器出现宕机,再次重启的时候,es会主动的读取translog之中的日志文件的数据,恢复到内存buffer和OS cache之中。
-
将现有的translog文件进行清空,然后在重新启动一个translog,此时commit就算是成功了,默认的是每隔30分钟进行一次commit,但是如果translog的文件过大,也会触发commit,整个commit过程就叫做一个flush操作,我们也可以通过ES API, 手动执行flush操作,手动将OS cache 的数据fsync到磁盘上面去,记录一个commit point,清空translog文件
补充:其实translog的数据也是先写入到OS cache之中的,默认每隔5秒之中将数据刷新到硬盘中去,也就是说,可能有5秒的数据仅仅停留在buffer或者translog文件的OS cache中,如果此时机器挂了,会丢失5秒的数据,但是这样的性能比较好,我们也可以将每次的操作都必须是直接fsync到磁盘,但是性能会比较差。
-
如果这时删除操作,commit的时候会产生一个.del文件,里面讲某个doc标记为delete状态,那么搜索的时候,会根据.del文件的状态,就知道那个文件被删除了。
-
如果这时更新操作,就是讲原来的doc标识为delete状态,然后重新写入一条数据即可。
-
buffer每次更新一次,就会产生一个segment file 文件,所以在默认情况之下,就会产生很多的segment file 文件,将会定期执行merge操作
-
每次merge的时候,就会将多个segment file 文件进行合并为一个,同时将标记为delete的文件进行删除,然后将新的segment file 文件写入到磁盘,这里会写一个commit point,标识所有的新的segment file,然后打开新的segment file供搜索使用。
2.5 ES查询过程
2.5.1 倒排序算法
查询有个算法叫倒排序:简单的说就是:通过分词把词语出现的id进行记录下来,再查询的时候先去查到哪些id包含这个数据,然后再根据id把数据查出来.
2.5.2 查询过程
-
客户端发送一个请求给coordinate node
-
协调节点将搜索的请求转发给所有的shard对应的primary shard 或replica shard
-
query phase:每一个shard 将自己搜索的结果(其实也就是一些唯一标识),返回给协调节点,有协调节点进行数据的合并,排序,分页等操作,产出最后的结果
-
fetch phase ,接着由协调节点,根据唯一标识去各个节点进行拉去数据,最总返回给客户端
2.5.3 查询原理
查询过程大体上分为查询和取回这两个阶段,广播查询请求到所有相关分片,并将它们的响应整合成全局排序后的结果集合,这个结果集合会返回给客户端。
查询阶段
当一个节点接收到一个搜索请求,那么这个节点就会变成协调节点,第一步就是将广播请求到搜索的每一个节点的分片拷贝,查询请求可以被某一个主分片或某一个副分片处理,协调节点将在之后的请求中轮训所有的分片拷贝来分摊负载。 每一个分片将会在本地构建一个优先级队列,如果客户端要求返回结果排序中从from 名开始的数量为size的结果集,每一个节点都会产生一个from+size大小的结果集,因此优先级队列的大小也就是from+size,分片仅仅是返回一个轻量级的结果给协调节点,包括结果级中的每一个文档的ID和进行排序所需要的信息。 协调节点将会将所有的结果进行汇总,并进行全局排序,最总得到排序结果。
取值阶段
查询过程得到的排序结果,标记处哪些文档是符合要求的,此时仍然需要获取这些文档返回给客户端 协调节点会确定实际需要的返回的文档,并向含有该文档的分片发送get请求,分片获取的文档返回给协调节点,协调节点将结果返回给客户端
3 ES 索引生命周期管理 ILM
index lifecycle management (ILM) policies.
ES索引生命周期管理分为4个阶段:hot、warm、cold、delete,其中hot主要负责对索引进行rollover操作,warm、cold、delete分别对rollover后的数据进一步处理(前提是配置了hot)。
phases | desc |
---|---|
hot | 主要处理时序数据的实时写入 |
warm | 可以用来查询,但是不再写入 |
cold | 索引不再有更新操作,并且查询也会很少 |
delete | 数据将被删除 |
上述4个阶段不是必须的
3.2 创建 ILM
创建索引生命周期 my_index,这里我以日志为例,温节点和冷节点为同一个节点集群。
打开创建索引界面
management -> Elasticsearch -> Index Lifecycle Policies -> Create policy
3.2.1 设置 ILM 名称
设置策略名称为 my_index
3.2.2 设置热阶段
开启滚动更新策略(Enable rollover):
a. 设置Maximum index size(最大索引大小)为50G
b. 设置Maximum age (最大存在时间) 为1天,保证每天最少一个索引
设置Index priority (索引优先级) 为 100 (优先级最高)
如果只是使用索引生命周期管理策略 冷热节点的管理,而不设置索引,可以关闭滚动更新策略。了解滚动更新
-
创建一个新索引
-
将新索引的is_write_index设置为true
-
将原始索引的is_write_索引设置为false
POST _aliases { "actions" : [{ "add" : { "index" : "my_index1" , "alias" : "my_index", "is_write_index": true } }] }
设置最大索引大小为50G. 经过测试,索引为50G 时对于不同的类型是一个较为通用的数据,当然,你还可以根据自己的需要调整。
3.2.3 设置温阶段
点击 Activate warm phase (激活温阶段)
关闭 Move to warm phase on rollover (滚动更新时移到温阶段)。如果开启,则在索引更新后,数据自动移动到温节点。
我们自己设置滚动更新策略。
a. 设置Timing for warm phase (温阶段计时) 3天进行滚动更新,
b. 选择 Select a node attribute to control shard allocation (选择节点属性以控制分片分配),选择温节点集群 temperature:warm(9)
设置Index priority (索引优先级) 为50 (优先级中等)
shrink是缩小索引的分片,让集群可以存储更多的索引。shrink的数值按照单块30~50G来算(腾讯推荐)。一般对于日志,不需要修改
force merge是合并segment, 清除已删除文件,对性能有提升。segment 建议大小为5GB(腾讯推荐) 。一般对于日志,不需要修改。如果是50g的索引,3块分片,一块分片就是17G,17 / 5 = 3.4,向下取整, 所以max_num_segments设置为3
#查询 segment GET _cat/segments/my_index1
3.2.4 设置冷阶段
点击 Activate cold phase (激活冷阶段)
我们设置滚动更新策略。
a. 设置Timing for code phase (冷段计时) 30天进行滚动更新,
b. 选择 Select a node attribute to control shard allocation (选择节点属性以控制分片分配),选择冷节点集群 temperature:warm(9)
c. 设置 Number of replicas (副本数) 为 0,因为在此阶段数据查询量很少,所以我们不需要保留副本,以减少磁盘空间,我们可以将数据备份保存在 对象存储或者其他地方。
开启 Freeze(冻结)设置。索引冻结后不能进行写的操作。
设置Index priority (索引优先级) 为 0 (优先级最低)
注意:修改冷阶段配置后,配置不会对已经在冷阶段的索引生效
kibana查询冻结索引
如果kibana 默认不能查询冻结的索引,要服务器托管查询冻结的索引数据,需要在 management -> kibana -> Advanced Settings -> Search 进行开启
实际是搜索时添加了参数ignore_throttled=false,例如:
GET /my_index/_search?ignore_throttled=false
3.2.5 设置删除阶段
点击 Activate delete phase (激活删除阶段)
设置删除阶段的计时 为90天
3.4 将生命周期管理添加到索引模版
选择索引模版 my_index,并设置滚动索引别名 my_index1
3.5 知识点分析
#查看生命周期管理策略 GET _ilm/policy/my_index
PUT _ilm/policy/logstashlog-default { "policy" : { "phases" : { "hot" : { "min_age" : "0ms", "actions" : { "rollover" : { "max_size" : "50gb", "max_age" : "4h" }, "set_priority" : { "priority" : 100 } } }, "delete" : { "min_age" : "7d", "actions" : { "delete":{} } } } } }
索引优先级
设置节点重新启动后恢复索引的优先级。优先级较高的索引在优先级较低的索引之前恢复。所以我们设置 热阶段优先级最高(100),其次是温阶段(50),冷阶段优先级最低(0)
副本数
副本数一般设置1-3个,默认为1个。副本数越少写越快,副本数越多读越快,所以在写入阶段,有一个副本保证高可用性即可。
分片数
单台机器上分片数越少越好,所以为1个。如果分片数大于等于3个,则建议分片数和副本分片数的和为集群(热)节点数,这样可以充分利用集群资源。在查询场景下,分片过多大概率会造成查询热点,没有少分片多副本性能好。
对于每个index的shard数量,可以根据数据总量、写入压力、节点数量等综合考量后设定,然后根据数据增长状态定期检测下shard数量是否合理。腾讯云CES技术团队的推荐方案是:
-
对于数据量较小(100GB以下)的index,往往写入压力查询压力相对较低,一般设置3~5个shard,number_of_replicas设置为1即可(也就是一主一从,共两副本) 。
-
对于数据量较大(100GB以上)的index: 一般把单个shard的数据量控制在(20GB~50GB) 让index压力分摊至多个节点:可通过index.routing.allocation.total_shards_per_node参数,强制限定一个节点上该index的shard数量,让shard尽量分配到不同节点上 综合考虑整个index的shard数量,如果shard数量(不包括副本)超过50个,就很可能引发拒绝率上升的问题,此时可考虑把该index拆分为多个独立的index,分摊数据量,同时配合routing使用,降低每个查询需要访问的shard数量。
冻结索引
使索引只读,并最大限度减小其内存占用。 了解详情
Elasticsearch索引将一些数据结构保存在内存中,以允许您高效地搜索它们并对它们进行索引。如果您有很多索引,那么这些数据结构所需的内存总量可能会很大。对于经常搜索的索引,最好将这些结构保留在内存中,因为重建它们需要时间。但是,您可能很少访问某些索引,因此希望在每次搜索时释放相应的内存并重建这些数据结构。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net