原文链接:http://laijianfeng.org/2018/08/Elasticsearch-%E5%88%86%E5%B8%83%E5%BC%8F%E7%89%B9%E6%80%A7/
本文的主要内容:
ES支持集群模式,是一个分布式系统,其好处主要有两个:
ES集群由多个ES实例组成
cerebro
cerebro 是一个ES Web管理工具,项目地址 https://github.com/lmenezes/cerebro
其配置文件为 conf/application.conf,启动 cerebro ,默认监听的地址为 0.0.0.0:9000
bin/cerebro
# 也可指定监听ip和端口号
bin/cerebro -Dhttp.port=1234 -Dhttp.address=127.0.0.1
访问 http://yourhost:9000 ,填写要监控的 ES 地址:http://eshost:9200 即可进入管理界面
cerebro管理界面
cerebro 节点信息
cerebro 集群配置
在cerebro管理界面中我们可以看到 ES节点、索引、shard的分布、集群参数配置等多种信息
如果只有一台机器,可以执行下面的命令,每次指定相同的集群名称,不同的节点名称和端口,即可在同一台机器上启动多个ES节点
bin/elasticsearch -Ecluster.name=my_cluster -Enode.name=node1 -Ehttp.port=9200 -d
作者的是在 virtualbox 上安装Ubuntu虚拟机,在安装好开发环境,正常启动ES之后,采取复制虚拟机的做法,复制后需要修改虚拟机的UUID,做法可自行上网搜索。
作者复制了两个,准备构建一个拥有三个ES节点的集群。启动虚拟机后可以进行关闭防火墙,配置hosts以使相互之间能够通过主机名访问,配置ssh免密访问等操作
分别修改ES节点中的 cluster.name
为相同名称,node.name
为各自的主机名,network.host
为 0.0.0.0
,discovery.zen.ping.unicast.hosts
列表中中加入各自的 node.name
在ES主目录下执行命令启动ES
bin/elasticsearch
查看日志可见集群搭建完毕
Cluster State 集群状态
与ES集群相关的数据称为cluster state,主要记录如下信息:
Master Node 主节点
node.master: true
Coordinating Node
Data Node 数据节点
node.data: true
提高系统可用性
提高系统可用性可从两个方面考虑:服务可用性和数据可用性
服务可用性
数据可用性
增大系统容量
如何将数据分布于所有节点上?
分片是ES支持PB级数据的基石
分片的分布
下图演示的是 3 个节点的集群中test_index的分片分布情况,创建时我们指定了3个分片和副本
PUT test_index
{
"settings": {
"number_of_replicas": 1,
"number_of_shards": 3
}
}
主副分片的分布
大致是均匀分布,实验中如果由于磁盘空间不足导致有分片未分配,为了测试可以将集群设置 cluster.routing.allocation.disk.threshold_enabled
设置为 false
此时增加节点是否能提高索引的数据容量?
不能,因为已经设置了分片数为 3 ,shard的数量已经确定,新增的节点无法利用,
此时增加副本数能否提高索引的读取吞吐量?
不能,因为新增的副本分片也是分布在这 3 台节点上,利用了同样的资源(CPU,内存,IO等)。如果要增加吞吐量,同时还需要增加节点的数量
分片数的设定很重要,需要提前规划好
30G
,shard数量最小为 2通过如下API可以查看集群健康状况,状态status包括以下三种:
GET _cluster/health
# 结果
{
"cluster_name": "elasticsearch",
"status": "yellow",
"timed_out": false,
"number_of_nodes": 1,
"number_of_data_nodes": 1,
"active_primary_shards": 115,
"active_shards": 115,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 111,
"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": 50.88495575221239
}
Failover 故障转移
集群由 3 个节点组成,名称分别为 master,Hadoop2,Hadoop3, 其中 master 为主节点,集群状态status为 green
集群状态green
如果此时 master 所在机器宕机导致服务终止,此时集群如何处理?
Hadoop2 和 Hadoop3 发现 master 无法响应一段时间后会发起 master 主节点选举,比如这里选择 Hadoop2 为 master 节点。由于此时主分片 P0 和 P2 下线,集群状态变为 Red
节点master宕机
node2 发现主分片 P0 和 P2 未分配,将 R0 和 R2 提升为主分片,此时由于所有主分片都正常分配,集群状态变为 yellow
image
Hadoop2 为 P0 和 P2 生成新的副本,集群状态变为绿色
image
最后看看 Hadoop2 打印的日志
image
文档最终会存储在分片上。文档选择分片需要文档到分片的映射算法,目的是使得文档均匀分布在所有分片上,以充分利用资源。
算法:
文档到分片的映射算法
ES通过如下的公式计算文档对应的分片
shard = hash(routing) % number_of_primary_shards
该算法与主分片数相关,这也是分片数一旦确定后便不能更改的原因
文档创建流程
文档创建流程
文档读取流程
文档读取流程
文档批量创建的流程
文档批量创建的流程 bulk
文档批量读取的流程
文档批量读取的流程 mget
脑裂问题,英文为split-brain,是分布式系统中的经典网络问题,如下图所示:
3个节点组成的集群,突然node1的网络和其他两个节点中断
image
node2与node3会重新选举master,比如node2成为了新的master,此时会更新cluster state
node1自己组成集群后,也更新cluster state
同一个集群有两个master,而且维护不同的cluster state,网络恢复后无法选择正确的master
image
解决方案为仅在可选举master-eligible节点数大于等于quorum时才可以进行master选举
quorum = master-eligible节点数/2 + 1
,例如3个master-eligible节点时,quorum 为2discovery.zen.minimun_master_nodes
为 quorum
即可避免脑裂问题image
倒排索引一旦生成,不能更改
其好处如下:
坏处为需要写入新文档时,必须重新构建倒排索引文件,然后替换老文件后,新文档才能被检索,导致文档实时性差
解决方案是新文档直接生成新的倒排索引文件,查询的时候同时查询所有的倒排文件,然后做结果的汇总计算即可
Lucene便是采用了这种方案,它构建的单个倒排索引称为segment,合在一起称为index,与ES中的Index概念不同,ES中的一个shard对应一个Lucene Index
Lucene会有一个专门的文件来记录所有的segment信息,称为commit point
image
refresh
segment写入磁盘的过程依然很耗时,可以借助文件系统缓存的特性,现将segment在缓存中创建并开放查询来进一步提升实时性,该过程在ES中被称为refresh
在refresh之前文档会先存储在一个buffer中,refresh时将buffer中的所有文档清空并生成segment
ES默认每1秒执行一次refresh,因此文档的实时性被提高到1秒,这也是ES被称为 近实时(Near Real Time)的原因
image
translog
如果在内存中的segment还没有写入磁盘前发生了宕机,那么其中的文档就无法恢复了,如何解决这个问题呢?
image
flush
flush负责将内存中的segment写入磁盘,主要做成如下的工作:
image
flush发生的时机主要有如下几种情况:
index.translog.flush_threshold_period
修改,之后无法修改index.translog.flush_threshold_size
控制,默认是512mb,每个index有自己的translogrefresh
refresh发生的时机主要有如下几种情况:
index.settings.refresh_interval
来设定,默认是1秒index.buffer
占满时,其大小通过indices.memory.index_buffer_size
设置,默认为JVM heap的10%,所有shard共享删除与更新文档
segment一旦生成就不能更改,那么如果你要删除文档该如何操作?
.del
文件,记录所有已经删除的文档,注意.del
上记录的是文档在Lucene内部的id.del
中所有的文档要更新文档如何进行呢?
整体视角
ES Index与Lucene Index的术语对照如下所示:
image
Segment Merging
随着segment的增多,由于一次查询的segment数增多,查询速度会变慢
ES会定时在后台进行segment merge的操作,减少segment的数量
通过force_merge api可以手动强制做segment merge的操作
作者:小旋锋的简书
链接:https://www.jianshu.com/p/467c3d2af913
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。