ElasticSearch - 集群
单机的 elasticsearch 做数据存储,必然面临两个问题:海量数据存储问题、单点故障问题。
- 海量数据存储问题:将索引库从逻辑上拆分为 N 个分片(shard),存储到多个节点
- 单点故障问题:将分片数据在不同节点备份(replica )
# 节点角色
节点类型 | 配置参数 | 默认值 | 节点职责 |
---|---|---|---|
master eligible | node.master | true | 备选主节点:主节点可以管理和记录集群状态、决定分片在哪个节点、处理创建和删除索引库的请求 |
data | node.data | true | 数据节点:存储数据、搜索、聚合、CRUD |
ingest | node.ingest | true | 数据存储之前的预处理 |
coordinating | 上面 3 个参数都为 false 则为 coordinating 节点 | 无 | 路由请求到其它节点合并其它节点处理的结果,返回给用户 |
# 分布式查询
es 中的每个节点角色都有自己不同的职责,因此建议集群部署时。每个节点都有独立的角色。
# 分布式存储
当新增文档时,应该保存到不同分片,保证数据均衡,那么 coordinating node 如何确定数据该存储到哪个分片呢?elasticsearch 会通过 hash 算法来计算文档应该存储到哪个分片:
shard = hash(_routing) % number_of_shards
说明:
- _routing 默认是文档的 id
- 算法与分片数量有关,因此索引库一旦创建,分片数量不能修改!
# 新增文档流程
elasticsearch 的查询分成两个阶段:
- scatter phase:分散阶段,coordinating node 会把请求分发到每一个分片
- gather phase:聚集阶段,coordinating node 汇总 data node 的搜索结果,并处理为最终结果集返回给用户
coordinating node 可以是 node1、node2、node3 任意一个,也可以是单独的结点
# 脑裂
默认情况下,每个节点都是 master eligible 节点,因此一旦 master 结点宕机,其他候选节点会选举一个称为主节点。当主节点与其他网络故障时,可能发生脑裂问题。
为了避免脑裂,需要要求选票超过 ( eligible 节点数量 + 1 )/ 2 才能当选为主,因此 eligible 节点数量最好是奇数。对应配置项是 discovery.zen.minimum_master_nodes
,在 es7.0 以后,已经成为默认配置,因此一般不会发生脑裂问题
# 部署 es 集群
部署 es 集群可以直接使用 docker-compose 来完成,不过要求你的 Linux 虚拟机至少有 4G 的内存空间
修改 linux 系统权限,修改 /etc/sysctl.conf
文件
vim /etc/sysctl.conf
添加
vm.max_map_count=262144
使命令生效
sysctl -p
首先编写一个 docker-compose 文件,内容如下:
version: '2.2'
services:
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
container_name: es01
environment:
- node.name=es01
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es02,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data01:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
- elastic
es02:
image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
container_name: es02
environment:
- node.name=es02
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es03
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data02:/usr/share/elasticsearch/data
networks:
- elastic
es03:
image: docker.elastic.co/elasticsearch/elasticsearch:7.12.1
container_name: es03
environment:
- node.name=es03
- cluster.name=es-docker-cluster
- discovery.seed_hosts=es01,es02
- cluster.initial_master_nodes=es01,es02,es03
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data03:/usr/share/elasticsearch/data
networks:
- elastic
volumes:
data01:
driver: local
data02:
driver: local
data03:
driver: local
networks:
elastic:
driver: bridge
错误提示:ERROR: Couldn't connect to Docker daemon at http+docker://localhost - is it running?
点击查看
主要原因是 docker (opens new window) 不是系统服务方式启动。
# 启动docker服务
service docker start
# 生成自启动服务
systemctl enable docker.service
# 查看服务状态,Active状态为:active(running)
systemctl status docker.service
# 集群状态监控
kibana 可以监控 es 集群,不过新版本需要依赖 es 的 x-pack 功能,配置比较复杂。
这里推荐使用 cerebro 来监控 es 集群状态,官方网址:https://github.com/lmenezes/cerebro
- 下载
cerebro-0.9.4.zip
- 运行
bin/cerebro.bat
- 访问
localhost:9000
- 输入一个节点的地址
# 创建索引库
PUT /itcast
{
"settings": {
"number_of_shards": 3, // 分片数量
"number_of_replicas": 1 // 副本数量
},
"mappings": {
"properties": {
// mapping映射定义 ...
}
}
}
可使用 cerebro 创建: more -> create index
# 查询文档存储的所在节点
GET /itcast/_search
{
"explain": true,
"query": {
"match_all": {}
}
}
# 故障转移
集群的 master 节点会监控集群中的节点状态,如果发现有节点宕机,会立即将宕机节点的分片数据迁移到其它节点,确保数据安全,这个叫做故障转移。
故障转移:
- master 宕机后,EligibleMaster 选举为新的主节点。
- master 节点监控分片、节点状态,将故障节点上的分片转移到正常节点,确保数据安全。