文档到分片的映射算法与存储原理
ElasticSearch通过分片(Shard)实现文档的分布式存储
每个文档根据routing参数(默认为文档ID)计算目标分片位置
计算公式为:
shard = hash(routing) % number_of_primary_shards
- 哈希算法:确保文档均匀分布到所有主分片(如MurmurHash3)
- 分片数不可修改:若
number_of_primary_shards变更,文档将无法通过相同算法定位(导致数据不可访问) - 自定义路由:可通过指定
routing(如论坛板块ID)实现相关文档聚合存储,提升查询效率
关键设计目的:
- 避免维护文档-分片映射表的高成本
- 同时解决随机分片/轮询分片导致的查询性能问题(无需广播查询所有分片)
文档操作流程详解
1 ) 单文档写入流程(以创建文档为例)
- 协调节点(Coordinating Node)(如Node3)接收
PUT /test_index/_doc/1请求 - 计算目标分片:
hash(1) % 3 = shard1,通过集群状态(Cluster State)确认Shard1位于Node2 - 转发请求至Node2(主分片P1)
- P1写入成功后,同步至副本分片R1(位于Node1)
- R1写入成功后返回响应,最终由Node3通知客户端。
2 ) 批量操作流程(Bulk API)
- 协调节点按
routing将文档分组,并发转发至对应主分片 - 主分片并行写入本地,异步同步至副本
- 所有分片响应成功后返回客户端
3 ) 文档读取流程
- 协调节点计算目标分片(同写入算法)
- 采用轮询策略从主/副本分片中选择一个节点查询(如优先副本分片以减轻主分片压力)
- 目标节点返回文档数据
脑裂问题(Split-Brain)解决方案
当网络分区导致集群分裂时(如Node1与Node2、Node3失联):
1 ) 问题本质:
- 分裂的子集群各自选举新Master,生成冲突的Cluster State。
- 网络恢复后出现双Master,集群状态无法自动修复。
2 ) 解决方案:法定人数(Quorum)机制
# 配置关键参数(elasticsearch.yml)
discovery.zen.minimum_master_nodes: 2 # 公式 = master_eligible_nodes / 2 + 1
- Quorum计算:3节点集群中,
Quorum = 3/2 + 1 = 2(向上取整)。 - 作用:
- 失联节点数不足Quorum时(如Node1单节点),禁止其选举Master。
- 仅健康节点(Node2+Node3)可选举新Master,保证集群可用性。
- 网络恢复后,隔离节点自动重新加入集群。
工程示例:基于NestJS的ES调用与配置
1 ) 方案1:基础文档操作服务
// src/elastic/elastic.service.ts
import { Injectable } from '@nestjs/common';
import { Client } from '@elastic/elasticsearch';
@Injectable()
export class ElasticService {
private readonly client: Client;
constructor() {
this.client = new Client({ node: 'http://localhost:9200' });
}
// 创建文档(指定路由)
async createDocument(index: string, id: string, body: object, routing?: string) {
return this.client.index({
index,
id,
body,
routing, // 自定义路由参数(如板块ID)
});
}
// 批量写入
async bulkCreate(index: string, docs: Array<{ id: string; body: object }>) {
const body = docs.flatMap(doc => [
{ index: { _index: index, _id: doc.id } },
doc.body
]);
return this.client.bulk({ body });
}
}
2 ) 方案2:分片策略优化配置
# ElasticSearch 索引配置(创建时固定分片数)
# PUT /test_index
{
"settings": {
"number_of_shards": 3, // 主分片数(创建后不可修改)
"number_of_replicas": 1, // 每个主分片的副本数
"routing": {
"allocation": {
"include": {
"box_type": "hot" // 自定义分片分配策略
}
}
}
}
}
3 ) 方案3:脑裂防护集群配置
# elasticsearch.yml(关键参数)
cluster.name: my-cluster
node.master: true # 节点可参与Master选举
node.data: true # 节点存储数据
discovery.zen.minimum_master_nodes: 2 # 3节点集群的Quorum值
discovery.zen.ping.unicast.hosts: ["node1", "node2", "node3"] # 集群节点列表
关键技术点总结
- 分片映射算法:依赖哈希路由确保数据均匀分布,分片数需预先合理规划。
- 读写扩散策略:
- 写操作:主分片同步副本(强一致性)。
- 读操作:主/副本轮询(负载均衡)。
- 脑裂防护:
- Quorum机制是分布式系统共识基础(如Paxos/Raft的变体)。
- 生产环境需部署3个Master节点并设置
minimum_master_nodes=2
- 路由优化场景:
- 时序数据按时间路由,日志数据按服务名路由,减少跨分片查询
通过分片策略、路由优化和集群配置的协同设计,可构建高可用、高性能的ElasticSearch分布式系统
初学者需重点理解分片不可变与Quorum机制的核心逻辑,此为分布式存储的基石设计原则
1371

被折叠的 条评论
为什么被折叠?



