忘机山人
#
https://appstore.lazycat.cloud/#/shop/detail/xu.deploy.elasticsearch
> 本章导读:本章将详细介绍 Elasticsearch 的核心概念,包括索引、文档、映射、分片、副本、集群和节点等,这些概念是理解和使用 Elasticsearch 的基础。
## 目录
- [前置知识](#前置知识)
- [索引(Index)](#索引index)
- [文档(Document)](#文档document)
- [映射(Mapping)](#映射mapping)
- [分片(Shard)](#分片shard)
- [副本(Replica)](#副本replica)
- [集群(Cluster)](#集群cluster)
- [节点(Node)](#节点node)
- [概念关系图](#概念关系图)
- [本章小结](#本章小结)
- [参考资料](#参考资料)
## 索引(Index)
### 什么是索引
索引是 Elasticsearch 中存储数据的逻辑命名空间,类似于关系型数据库中的"数据库"概念。一个索引包含一组具有相似特征的文档。
### 索引命名规则
索引名称必须遵循以下规则:
- 只能使用小写字母
- 不能包含 `\`、`/`、`*`、`?`、`"`、``、`|`、空格、逗号、`#`
- 7.0 之前可以包含冒号 `:`,但已废弃
- 不能以 `-`、`_`、`+` 开头
- 不能是 `.` 或 `..`
- 长度不能超过 255 字节
### 索引示例
```json
// 创建索引
PUT /products
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1
}
}
// 查看索引信息
GET /products
// 查看所有索引
GET /_cat/indices?v
// 删除索引
DELETE /products
```
### 索引设置
索引有两类设置:
**静态设置**(创建后不可修改):
- `number_of_shards`:主分片数量
**动态设置**(可随时修改):
- `number_of_replicas`:副本数量
- `refresh_interval`:刷新间隔
- `max_result_window`:最大返回结果数
```json
// 修改动态设置
PUT /products/_settings
{
"index": {
"number_of_replicas": 2,
"refresh_interval": "30s"
}
}
```
## 文档(Document)
### 什么是文档
文档是 Elasticsearch 中的基本数据单元,以 JSON 格式存储。每个文档都属于一个索引,并有一个唯一的 ID。
### 文档结构
一个文档包含以下元数据:
| 元数据 | 说明 |
|--------|------|
| `_index` | 文档所属的索引 |
| `_id` | 文档的唯一标识符 |
| `_source` | 文档的原始 JSON 内容 |
| `_version` | 文档版本号 |
| `_seq_no` | 序列号,用于并发控制 |
| `_primary_term` | 主分片任期号 |
### 文档操作示例
```json
// 创建文档(指定 ID)
PUT /products/_doc/1
{
"name": "iPhone 15",
"price": 7999,
"category": "手机",
"brand": "Apple",
"created_at": "2024-01-01"
}
// 创建文档(自动生成 ID)
POST /products/_doc
{
"name": "MacBook Pro",
"price": 14999,
"category": "笔记本",
"brand": "Apple"
}
// 获取文档
GET /products/_doc/1
// 更新文档
POST /products/_update/1
{
"doc": {
"price": 7499
}
}
// 删除文档
DELETE /products/_doc/1
```
### 文档 ID
- **自动生成**:使用 POST 方法时,ES 自动生成 20 字符的 Base64 编码 ID
- **手动指定**:使用 PUT 方法时,可以指定任意字符串作为 ID
```json
// 自动生成 ID
POST /products/_doc
{
"name": "Product A"
}
// 返回: "_id": "abc123xyz..."
// 手动指定 ID
PUT /products/_doc/my-product-001
{
"name": "Product B"
}
// 返回: "_id": "my-product-001"
```
## 映射(Mapping)
### 什么是映射
映射定义了文档及其字段如何存储和索引。类似于关系型数据库中的表结构定义(Schema)。
### 字段类型
Elasticsearch 支持多种字段类型:
**核心类型**:
| 类型 | 说明 | 示例 |
|------|------|------|
| `text` | 全文搜索文本 | 商品描述、文章内容 |
| `keyword` | 精确值 | 状态、标签、ID |
| `long` | 长整型 | 大数值 |
| `integer` | 整型 | 数量、年龄 |
| `double` | 双精度浮点 | 价格、评分 |
| `boolean` | 布尔值 | 是否上架 |
| `date` | 日期 | 创建时间 |
| `object` | JSON 对象 | 嵌套属性 |
| `nested` | 嵌套对象数组 | 评论列表 |
**特殊类型**:
| 类型 | 说明 |
|------|------|
| `geo_point` | 地理坐标点 |
| `geo_shape` | 地理形状 |
| `ip` | IP 地址 |
| `completion` | 自动补全 |
| `dense_vector` | 稠密向量 |
### 映射示例
```json
// 创建索引时定义映射
PUT /products
{
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "standard",
"fields": {
"keyword": {
"type": "keyword"
}
}
},
"price": {
"type": "double"
},
"category": {
"type": "keyword"
},
"description": {
"type": "text"
},
"created_at": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
},
"is_available": {
"type": "boolean"
},
"tags": {
"type": "keyword"
},
"location": {
"type": "geo_point"
}
}
}
}
// 查看映射
GET /products/_mapping
```
### 动态映射
当索引一个包含新字段的文档时,Elasticsearch 会自动推断字段类型:
| JSON 类型 | 推断的 ES 类型 |
|-----------|----------------|
| `true` / `false` | `boolean` |
| 整数 | `long` |
| 浮点数 | `double` |
| 日期格式字符串 | `date` |
| 其他字符串 | `text` + `keyword` |
| 对象 | `object` |
| 数组 | 取决于第一个元素 |
```json
// 控制动态映射行为
PUT /products
{
"mappings": {
"dynamic": "strict", // true(默认)/false/strict
"properties": {
"name": { "type": "text" }
}
}
}
```
- `true`:自动添加新字段(默认)
- `false`:忽略新字段,不索引但保存在 `_source`
- `strict`:遇到新字段抛出异常
## 分片(Shard)
### 什么是分片
分片是索引的水平分割单元。每个分片本质上是一个独立的 Lucene 索引,可以独立执行索引和搜索操作。
### 为什么需要分片
1. **水平扩展**:数据量超过单节点容量时,分片允许数据分布到多个节点
2. **并行处理**:搜索可以在多个分片上并行执行,提高性能
3. **高可用**:配合副本机制,提供故障容错能力
### 分片类型
```
┌─────────────────────────────────────────────────────────┐
│ 索引 (Index) │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Primary 0 │ │ Primary 1 │ │ Primary 2 │ │
│ │ (主分片) │ │ (主分片) │ │ (主分片) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Replica 0 │ │ Replica 1 │ │ Replica 2 │ │
│ │ (副本分片) │ │ (副本分片) │ │ (副本分片) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
```
- **主分片(Primary Shard)**:处理索引写入请求,每个文档只属于一个主分片
- **副本分片(Replica Shard)**:主分片的复制,用于故障转移和读取负载均衡
### 分片配置
```json
// 创建索引时指定分片数
PUT /products
{
"settings": {
"number_of_shards": 3, // 主分片数(创建后不可修改)
"number_of_replicas": 1 // 每个主分片的副本数(可动态修改)
}
}
```
### 分片数量规划
**经验法则**:
- 单个分片大小建议在 10GB - 50GB 之间
- 分片数 = 预计数据量 / 单分片大小
- 考虑未来增长,但不要过度分片
**过度分片的问题**:
- 每个分片消耗资源(内存、文件句柄)
- 搜索需要协调更多分片,增加开销
- 集群状态膨胀
```json
// 查看分片分布
GET /_cat/shards/products?v
```
## 副本(Replica)
### 什么是副本
副本是主分片的完整复制。每个主分片可以有零个或多个副本。
### 副本的作用
1. **高可用**:主分片所在节点故障时,副本可以提升为主分片
2. **读取扩展**:搜索请求可以在主分片或副本上执行,提高读取吞吐量
3. **数据冗余**:防止数据丢失
### 副本配置
```json
// 修改副本数量
PUT /products/_settings
{
"index": {
"number_of_replicas": 2
}
}
```
### 副本分配规则
- 副本不会与其主分片分配在同一节点上
- 如果节点数少于副本数 + 1,部分副本将无法分配
```
节点数 = 1,副本数 = 1
┌─────────────────┐
│ Node 1 │
│ ┌───────────┐ │
│ │ Primary 0 │ │
│ └───────────┘ │
│ ┌───────────┐ │
│ │ Replica 0 │ │ ← 无法分配!
│ │ UNASSIGNED│ │
│ └───────────┘ │
└─────────────────┘
节点数 = 2,副本数 = 1
┌─────────────────┐ ┌─────────────────┐
│ Node 1 │ │ Node 2 │
│ ┌───────────┐ │ │ ┌───────────┐ │
│ │ Primary 0 │ │ │ │ Replica 0 │ │ ← 正常分配
│ └───────────┘ │ │ └───────────┘ │
└─────────────────┘ └─────────────────┘
```
## 集群(Cluster)
### 什么是集群
集群是一组协同工作的 Elasticsearch 节点。集群通过唯一的名称标识,默认名称为 `elasticsearch`。
### 集群健康状态
集群有三种健康状态:
| 状态 | 颜色 | 说明 |
|------|------|------|
| Green | 🟢 | 所有主分片和副本分片都已分配 |
| Yellow | 🟡 | 所有主分片已分配,但部分副本未分配 |
| Red | 🔴 | 部分主分片未分配,数据不完整 |
```json
// 查看集群健康状态
GET /_cluster/health
// 返回示例
{
"cluster_name": "my-cluster",
"status": "green",
"number_of_nodes": 3,
"number_of_data_nodes": 3,
"active_primary_shards": 10,
"active_shards": 20,
"relocating_shards": 0,
"initializing_shards": 0,
"unassigned_shards": 0
}
```
### 集群配置
```yaml
# elasticsearch.yml
cluster.name: my-cluster
node.name: node-1
network.host: 0.0.0.0
discovery.seed_hosts: ["node1:9300", "node2:9300", "node3:9300"]
cluster.initial_master_nodes: ["node-1", "node-2", "node-3"]
```
## 节点(Node)
### 什么是节点
节点是集群中的单个 Elasticsearch 实例。每个节点都有唯一的名称和角色。
### 节点角色
| 角色 | 配置 | 说明 |
|------|------|------|
| Master | `node.roles: [master]` | 管理集群状态、索引创建删除、分片分配 |
| Data | `node.roles: [data]` | 存储数据、执行 CRUD、搜索、聚合 |
| Ingest | `node.roles: [ingest]` | 执行 Ingest Pipeline 预处理 |
| Coordinating | `node.roles: []` | 路由请求、合并结果(无特定角色) |
| ML | `node.roles: [ml]` | 执行机器学习任务 |
| Remote Cluster Client | `node.roles: [remote_cluster_client]` | 跨集群搜索 |
### 节点角色组合
```yaml
# 专用主节点
node.roles: [master]
# 专用数据节点
node.roles: [data]
# 数据 + Ingest 节点
node.roles: [data, ingest]
# 协调节点(无角色)
node.roles: []
# 默认(所有角色)
node.roles: [master, data, data_content, data_hot, data_warm, data_cold, ingest, ml, remote_cluster_client, transform]
```
### 节点信息查看
```json
// 查看所有节点
GET /_cat/nodes?v
// 查看节点详细信息
GET /_nodes
// 查看特定节点统计
GET /_nodes/stats
```
## 概念关系图
```
┌─────────────────────────────────────────────────────────────────────┐
│ Cluster (集群) │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Node 1 (节点) │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ Index (索引) │ │ │
│ │ │ ┌─────────────┐ ┌─────────────┐ │ │ │
│ │ │ │ Shard P0 │ │ Shard R1 │ │ │ │
│ │ │ │ ┌─────────┐ │ │ │ │ │ │
│ │ │ │ │Document │ │ │ │ │ │ │
│ │ │ │ │ _id: 1 │ │ │ │ │ │ │
│ │ │ │ │ _source │ │ │ │ │ │ │
│ │ │ │ └─────────┘ │ │ │ │ │ │
│ │ │ │ ┌─────────┐ │ │ │ │ │ │
│ │ │ │ │Document │ │ │ │ │ │ │
│ │ │ │ │ _id: 2 │ │ │ │ │ │ │
│ │ │ │ └─────────┘ │ │ │ │ │ │
│ │ │ └─────────────┘ └─────────────┘ │ │ │
│ │ │ │ │ │
│ │ │ Mapping (映射): 定义字段类型和索引方式 │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────┐ │
│ │ Node 2 (节点) │ │
│ │ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Shard P1 │ │ Shard R0 │ │ │
│ │ └─────────────┘ └─────────────┘ │ │
│ └─────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────┘
```
### 概念对比:ES vs 关系型数据库
| Elasticsearch | 关系型数据库 | 说明 |
|---------------|--------------|------|
| Index | Database | 数据的逻辑容器 |
| Mapping | Schema | 数据结构定义 |
| Document | Row | 数据的基本单元 |
| Field | Column | 数据的属性 |
| Shard | Partition | 数据的物理分割 |
> ⚠️ **注意**:这个对比仅用于帮助理解,ES 和关系型数据库的设计理念有本质区别。
## 本章小结
本章介绍了 Elasticsearch 的核心概念:
1. **索引(Index)**:存储数据的逻辑命名空间,包含设置和映射
2. **文档(Document)**:基本数据单元,JSON 格式,有唯一 ID
3. **映射(Mapping)**:定义字段类型和索引方式,支持动态和显式映射
4. **分片(Shard)**:索引的水平分割,实现分布式存储和并行处理
5. **副本(Replica)**:主分片的复制,提供高可用和读取扩展
6. **集群(Cluster)**:多节点协同工作,有 Green/Yellow/Red 三种状态
7. **节点(Node)**:集群中的单个实例,可配置不同角色
理解这些概念是使用 Elasticsearch 的基础,后续章节将在此基础上深入讲解各个功能。

## 参考资料
- [Elasticsearch 索引概念](https://www.elastic.co/guide/en/elasticsearch/reference/current/documents-indices.html)
- [映射类型](https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html)
- [分片分配](https://www.elastic.co/guide/en/elasticsearch/reference/current/index-modules-allocation.html)
- [集群健康](https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-health.html)
评论
0暂无评论