集群
核心概念
集群
一个集群可以有一个或者多个节点
不同的集群通过不同的名字来区分,默认名字“elasticsearch“
通过配置文件修改,或者在命令行中 -E cluster.name=es-cluster进行设定
节点
节点是一个Elasticsearch的实例
本质上就是一个JAVA进程
一台机器上可以运行多个Elasticsearch进程,但是生产环境一般建议一台机器上只运行一个Elasticsearch实例
每一个节点都有名字,通过配置文件配置,或者启动时候 -E node.name=node1指定
每一个节点在启动之后,会分配一个UID,保存在data目录下
节点类型
- Master Node:主节点
- Master eligible nodes:可以参与选举的合格节点
- Data Node:数据节点
- Coordinating Node:协调节点
- 其他节点
Master eligible nodes和Master Node
- 每个节点启动后,默认就是一个Master eligible节点
可以设置 node.master: false禁止 - Master-eligible节点可以参加选主流程,成为Master节点
- 当第一个节点启动时候,它会将自己选举成Master节点
- 每个节点上都保存了集群的状态,只有Master节点才能修改集群的状态信息
集群状态(Cluster State) ,维护了一个集群中,必要的信息
所有的节点信息
所有的索引和其相关的Mapping与Setting信息
分片的路由信息
Master Node的职责
处理创建,删除索引等请求,负责索引的创建与删除
决定分片被分配到哪个节点
维护并且更新Cluster State
Master Node的最佳实践
Master节点非常重要,在部署上需要考虑解决单点的问题
为一个集群设置多个Master节点,每个节点只承担Master 的单一角色
选主的过程
互相Ping对方,Node ld 低的会成为被选举的节点
其他节点会加入集群,但是不承担Master节点的角色。一旦发现被选中的主节点丢失,就会选举出新的Master节点
Data Node & Coordinating Node
Data Node
可以保存数据的节点,叫做Data Node,负责保存分片数据。在数据扩展上起到了
至关重要的作用
节点启动后,默认就是数据节点。可以设置node.data: false 禁止
由Master Node决定如何把分片分发到数据节点上
通过增加数据节点可以解决数据水平扩展和解决数据单点问题
Coordinating Node
负责接受Client的请求, 将请求分发到合适的节点,最终把结果汇集到一起
每个节点默认都起到了Coordinating Node的职责
分片(Primary Shard & Replica Shard)
主分片(Primary Shard)
用以解决数据水平扩展的问题。通过主分片,可以将数据分布到集群内的所有节点之上
一个分片是一个运行的Lucene的实例
主分片数在索引创建时指定,后续不允许修改,除非Reindex
副本分片(Replica Shard)
用以解决数据高可用的问题。 副本分片是主分片的拷贝
副本分片数,可以动态调整
增加副本数,还可以在一定程度上提高服务的可用性(读取的吞吐)
# 指定索引的主分片和副本分片数
PUT /blogs
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
分片的设定
对于生产环境中分片的设定,需要提前做好容量规划
- 分片数设置过小
导致后续无法增加节点实现水平扩展
单个分片的数据量太大,导致数据重新分配耗时 - 分片数设置过大,
7.0 开始,默认主分片设置成1,解决了over-sharding(分片过度)的问题
影响搜索结果的相关性打分,影响统计结果的准确性
单个节点上过多的分片,会导致资源浪费,同时也会影响性能
#查看集群的健康状况
GET _cluster/health
集群状态
status
Green: 主分片与副本都正常分配
Yellow: 主分片全部正常分配,有副本分片未能正常分配
Red: 有主分片未能分配。例如,当服务器的磁盘容量超过85%时,去创建了一个新的索引
API
GET /_cat/nodes?v #查看节点信息
GET /_cat/health?v #查看集群当前状态:红、黄、绿
GET /_cat/shards?v #查看各shard的详细情况
GET /_cat/shards/{index}?v #查看指定分片的详细情况
GET /_cat/master?v #查看master节点信息
GET /_cat/indices?v #查看集群中所有index的详细信息
GET /_cat/indices/{index}?v #查看集群中指定index的详细信息
生产环境常见集群部署方式
单一角色
不同角色的节点:Master eligible / Data / Ingest / Coordinating /Machine Learning
在生产环境中:
- 根据数据量,写入和查询的吞吐量,选择合适的部署方式
- 建议设置单一角色的节点
#Master节点
node.master: true
node.ingest: false
node.data: false
#data节点
node.master: false
node.ingest: false
node.data: true
#ingest 节点
node.master: false
node.ingest: true
node.data: false
#coordinate节点
node.master: false
node.ingest: false
node.data: false
单一角色职责分离的好处:
- 单一 master eligible nodes: 负责集群状态(cluster state)的管理
使用低配置的CPU,RAM和磁盘 - 单一 data nodes: 负责数据存储及处理客户端请求
使用高配置的CPU,RAM和磁盘 - 单一ingest nodes: 负责数据处理
使用高配置CPU; 中等配置的RAM; 低配置的磁盘 - 单一Coordinating Only Nodes(Client Node)
使用高配置CPU; 高配置的RAM; 低配置的磁盘
增加节点水平扩展场景
当磁盘容量无法满足需求时,可以增加数据节点;
磁盘读写压力大时,增加数据节点
当系统中有大量的复杂查询及聚合时候,增加Coordinating节点,增加查询的性能
读写分离架构
异地多活架构
集群处在三个数据中心,数据三写,GTM分发读请求
Hot & Warm 架构
为什么要设计Hot & Warm 架构?
- ES数据通常不会有 Update操作;
- 适用于Time based索引数据,同时数据量比较大的场景。
- 引入 Warm节点,低配置大容量的机器存放老数据,以降低部署成本
两类数据节点,不同的硬件配置:
- Hot节点(通常使用SSD)︰索引不断有新文档写入。
- Warm 节点(通常使用HDD)︰索引不存在新数据的写入,同时也不存在大量的数据查询
Hot Nodes
用于数据的写入:
lndexing 对 CPU和IO都有很高的要求,所以需要使用高配置的机器
存储的性能要好,建议使用SSD
Warm Nodes
用于保存只读的索引,比较旧的数据。通常使用大容量的磁盘
配置
使用Shard Filtering实现Hot&Warm node间的数据迁移
- node.attr来指定node属性:hot或是warm。
- 在index的settings里通过index.routing.allocation来指定索引(index)到一个满足要求的node
使用 Shard Filtering,步骤分为以下几步:
- 标记节点(Tagging)
- 配置索引到Hot Node
- 配置索引到 Warm节点
标记节点
需要通过“node.attr”来标记一个节点
节点的attribute可以是任何的key/value
可以通过elasticsearch.yml 或者通过-E命令指定
# 标记一个 Hot 节点
elasticsearch.bat -E node.name=hotnode -E cluster.name=tulingESCluster -E http.port=9200 -E path.data=hot_data -E node.attr.my_node_type=hot
# 标记一个 warm 节点
elasticsearch.bat -E node.name=warmnode -E cluster.name=tulingESCluster -E http.port=9201 -E path.data=warm_data -E node.attr.my_node_type=warm
# 查看节点
GET /_cat/nodeattrs?v
配置Hot数据
创建索引时候,指定将其创建在hot节点上
# 配置到 Hot节点
PUT /index-2022-05
{
"settings":{
"number_of_shards":2,
"number_of_replicas":0,
"index.routing.allocation.require.my_node_type":"hot"
}
}
POST /index-2022-05/_doc
{
"create_time":"2022-05-27"
}
#查看索引文档的分布
GET _cat/shards/index-2022-05?v
旧数据移动到Warm节点
Index.routing.allocation是一个索引级的dynamic setting,可以通过API在后期进行设定
# 配置到 warm 节点
PUT /index-2022-05/_settings
{
"index.routing.allocation.require.my_node_type":"warm"
}
GET _cat/shards/index-2022-05?v
ES底层读写工作原理
写请求是写入 primary shard,然后同步给所有的 replica shard;读请求可以从 primary shard 或 replica shard 读取,采用的是随机轮询算法。
写数据核心概念
- segment file: 存储倒排索引的文件,每个segment本质上就是一个倒排索引,每秒都会生成一个segment文件,当文件过多时es会自动进行segment merge(合并文件),合并时会同时将已经标注删除的文档物理删除。
- commit point: 记录当前所有可用的segment,每个commit point都会维护一个.del文件,即每个.del文件都有一个commit point文件(es删除数据本质是不属于物理删除),当es做删改操作时首先会在.del文件中声明某个document已经被删除,文件内记录了在某个segment内某个文档已经被删除,当查询请求过来时在segment中被删除的文件是能够查出来的,但是当返回结果时会根据commit point维护的那个.del文件把已经删除的文档过滤掉
- translog日志文件: 为了防止elasticsearch宕机造成数据丢失保证可靠存储,es会将每次写入数据同时写到translog日志中。
- os cache:操作系统里面,磁盘文件其实都有一个东西,叫做os cache,操作系统缓存,就是说数据写入磁盘文件之前,会先进入os cache,先进入操作系统级别的一个内存缓存中去
- Refresh:将文档先保存在Index buffer中,以refresh_interval为间隔时间,定期清空buffer,生成 segment,借助文件系统缓存的特性,先将segment放在文件系统缓存中,并开放查询,以提升搜索的实时性
- Translog:Segment没有写入磁盘,即便发生了当机,重启后,数据也能恢复,从ES6.0开始默认配置是每次请求都会落盘
- Flush:删除旧的translog 文件
生成Segment并写入磁盘│更新commit point并写入磁盘。ES自动完成,可优化点不多
ES写入数据的过程
- 客户端选择一个node发送请求过去,这个node就是coordinating node (协调节点)
- coordinating node,对document进行路由,将请求转发给对应的node
- node上的primary shard处理请求,然后将数据同步到replica node
- coordinating node如果发现primary node和所有的replica node都搞定之后,就会返回请求到客户端
ES读取数据的过程
根据id查询
根据 doc id 进行 hash,判断出来当时把 doc id 分配到了哪个 shard 上面去,从那个 shard 去查询。
客户端发送请求到任意一个 node,成为 coordinate node 。
coordinate node 对 doc id 进行哈希路由,将请求转发到对应的 node,此时会使用 round-robin 随机轮询算法,在 primary shard 以及其所有 replica 中随机选择一个,让读请求负载均衡。
接收请求的 node 返回 document 给 coordinate node 。
coordinate node 返回 document 给客户端。
根据关键词查询
客户端发送请求到一个 coordinate node 。
协调节点将搜索请求转发到所有的 shard 对应的 primary shard 或 replica shard ,都可以。
query phase:每个 shard 将自己的搜索结果返回给协调节点,由协调节点进行数据的合并、排序、分页等操作,产出最终结果。
fetch phase:接着由协调节点根据 doc id 去各个节点上拉取实际的 document 数据,最终返回给客户端。