上一篇:ElasticSearch 04 -- 进阶_fengxianaa的博客-CSDN博客
1. 相关概念
- 节点:一个个 ES 实例
- 集群:一组节点的 cluster name 一样
- 分片:集群下,一个索引可以拆成多个分片,存储到不同的节点上,有点儿类似数据库的分表
- 主、副分片:分片有主、副之分,每个主分片可以有多个副分片,副分片存储的数据跟主分片一样
- 下图中主分片和副分片不再一台机器上,避免一个节点宕机数据丢失
2. 搭建
准备3个虚拟机,虚拟机复制参考:虚拟机02--Virtual Box 虚拟机复制_fengxianaa的博客-CSDN博客
我的三台机器,分别是:192.168.56.107、192.168.56.108、192.168.56.109
修改 107 上的 elasticsearch.yml
# 集群名称,3个节点的cluster.name一样,表示这3个节点是一个集群 cluster.name: my-es # 节点名称,唯一 node.name: node-1 # 是否有资格成为主节点,true:有资格竞争主节点的位置 node.master: true #是否存储数据 node.data: true # 限制单个机器上可以开启的ES存储实例的个数,如果在一台机器上搭建集群可以用这个配置 node.max_local_storage_nodes: 3 # 暴露一个IP,供外网访问 network.host: 192.168.56.107 # http访问的端口号 http.port: 9200 # 节点之间沟通端口,默认9300 transport.tcp.port: 9700 #es7.x 之后新增的配置,用于节点发现 discovery.seed_hosts: ["192.168.56.107:9700","192.168.56.108:9700","192.168.56.109:9700"] #es7.x 之后新增的配置,初始化一个新的集群时,根据这个配置选举master cluster.initial_master_nodes: ["node-1","node-2","node-3"]
- 修改 108 上的 elasticsearch.yml
# 集群名称,3个节点的cluster.name一样,表示这3个节点是一个集群 cluster.name: my-es # 节点名称,唯一 node.name: node-2 # 是否有资格成为主节点,true:有资格竞争主节点的位置 node.master: true #是否存储数据 node.data: true # 限制单个机器上可以开启的ES存储实例的个数,如果在一台机器上搭建集群可以用这个配置 node.max_local_storage_nodes: 3 # 暴露一个IP,供外网访问 network.host: 192.168.56.108 # http访问的端口号 http.port: 9200 # 节点之间沟通端口,默认9300 transport.tcp.port: 9700 #es7.x 之后新增的配置,用于节点发现 discovery.seed_hosts: ["192.168.56.107:9700","192.168.56.108:9700","192.168.56.109:9700"] #es7.x 之后新增的配置,初始化一个新的集群时,根据这个配置选举master cluster.initial_master_nodes: ["node-1","node-2","node-3"]
- 修改 109 上的 elasticsearch.yml
# 集群名称,3个节点的cluster.name一样,表示这3个节点是一个集群 cluster.name: my-es # 节点名称,唯一 node.name: node-3 # 是否有资格成为主节点,true:有资格竞争主节点的位置 node.master: true #是否存储数据 node.data: true # 限制单个机器上可以开启的ES存储实例的个数,如果在一台机器上搭建集群可以用这个配置 node.max_local_storage_nodes: 3 # 暴露一个IP,供外网访问 network.host: 192.168.56.109 # http访问的端口号 http.port: 9200 # 节点之间沟通端口,默认9300 transport.tcp.port: 9700 #es7.x 之后新增的配置,用于节点发现 discovery.seed_hosts: ["192.168.56.107:9700","192.168.56.108:9700","192.168.56.109:9700"] #es7.x 之后新增的配置,初始化一个新的集群时,根据这个配置选举master cluster.initial_master_nodes: ["node-1","node-2","node-3"]
分别启动这 3 个 ES,启动前先删除 /home/soft/elasticsearch-7.8.0/data 下的数据
107:
108:
109:
查看集群状态:http://192.168.56.107:9200/_cat/health?v
解释:
cluster: 集群名称
status: 集群状态,
green: 健康
yellow: 缺失副分片
red: 缺失主分片
node.total: 在线的节点数量
node.data: 在线的数据节点数量,elasticsearch.yml中 node.data=true 的是数据节点
shards: 总分片数量
pri: 主分片数量
relo: 迁移的分片数量,正常为 0
init: 初始化的分片数量,正常为 0
unassign: 未分配的分片,正常为 0
pending_tasks: 准备中的任务,比如:迁移分片等,正常为 0
max_task_wait_time: 任务最长等待时间
active_shards_percent:正常分片的百分比,一般应该是 100%
3. kibana 管理集群
修改 Kibana 的配置文件:kibana.yml
然后启动 kibana
浏览器访问:http://192.168.56.107:5601/
4. Java API
java API 访问集群,只是在创建 client 的地方做修改,比如:
RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(
new HttpHost("192.168.56.107",9200,"http"),
new HttpHost("192.168.56.108",9200,"http"),
new HttpHost("192.168.56.109",9200,"http")));
5. 分片配置
集群下,创建所索引时,默认会自动设置一个主分片和一个副分片,并且不再同一个节点上
1. 创建索引时指定分片
在创建索引的时候可以通过 settings 设置分片
在 Kibana 中执行下面命令
# 1. 删除索引
DELETE fengxiansheng
# 2. 创建索引时,指定分片数量
PUT fengxiansheng
{
"mappings": {
"properties": {
"name":{
"type": "text"
}
}
},
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
# "number_of_shards": 3, 表示有3个主分片
# "number_of_replicas": 1, 表示每个主分片有1个副分片
Kibana 上查看:
ES的自动分片方式保证了,任何一个节点宕机,都不影响数据的完整性
2. 分片自动平衡
如果 node-3 宕机,那么它上面的分片会自动转移到 node-1、node-2 上
等一会儿刷新页面
重启 node-3 后,就重新分配两个分片
3. 总结
- 创建所索引时,默认会自动设置一个主分片和一个副分片,并且不再同一个节点上
- 可以通过 settings 设置分片数量
- 分片自动平衡
- 节点宕机后,挂掉的节点会自动分配到其他节点上
- 分片数量一旦确定,不能修改
- 推荐分片方案:
- 每个分片 10-30G
- 分片数量 = 节点数的 1-3 倍
6. 分片路由
- 节点宕机后,挂掉的节点会自动分配到其他节点上
- 每个分片 10-30G
- 分片数量 = 节点数的 1-3 倍
存储数据时,ES会经过一定的计算,得到分片编号,然后把数据放到指定的分片上
计算规则:分片编号 = 文档id的hash % 主分片数量
假如:一个文档 id 的哈希值是 15,主分片数量是 3,那么这个文档就会存储到 0 号分片上
所以 ES 规定一档分片数量确定,不能修改,否则一旦修改,有些数据就查不到了
7. 脑裂
正常情况下集群中只会有一个Master,脑裂是指:集群中出现多个Master
原因:Master 短暂的不可用或者连不上
- 网络原因:
- Master所在机器突然脱离了正常的网络,跟其他机器不能连接,但是实际上还运行着,此时其他节点得不到主节点的响应认为主节点挂掉了,会重新选取 Master,但过了一会儿,原来的Master网络通信又恢复正常
- 节点负载:
- Master 收到大量请求,处理不过来,导致暂时停止响应
- 一般这种情况因为:Master 存储数据(node.data=true),在处理客户端请求的同时,又管理集群
- JVM内存回收
- Master 内存设置的比较小,JVM大规模回收内存,导致暂时停止响应
解决:
- discovery.zen.ping_timeout :节点响应时间,默认3秒,可以调大一些,防止网络原因导致的脑裂
- 角色分离:Master 不存储数据(node.data=false),同样的数据节点:node.master=false,不参与Master的选举
- JVM内存调整:如果资源充足,可以修改jvm.properties,最好修改为系统内存的50%
8. 集群扩容
新增复制一个虚拟机 192.168.56.110,修改 elasticsearch.yml
# 集群名称,3个节点的cluster.name一样,表示这3个节点是一个集群 cluster.name: my-es # 节点名称,唯一 node.name: node-4 # 是否有资格成为主节点,true:有资格竞争主节点的位置 node.master: true #是否存储数据 node.data: true # 限制单个机器上可以开启的ES存储实例的个数 node.max_local_storage_nodes: 3 # 暴露一个IP,供外网访问 network.host: 192.168.56.110 # http访问的端口号 http.port: 9200 # 节点之间沟通端口,默认9300 transport.tcp.port: 9700 # 加上110的ip和端口 discovery.seed_hosts: ["192.168.56.107:9700","192.168.56.108:9700","192.168.56.109:9700","192.168.56.110:9700"] #es7.x 之后新增的配置,初始化一个新的集群时,根据这个配置选举master cluster.initial_master_nodes: ["node-1","node-2","node-3","node-4"]
启动ES,启动前先删除 /home/soft/elasticsearch-7.8.0/data 下的数据
结果:
Kibana 上查看



