Elasticsearch 第2章:核心概念

忘机山人

发布于218天前
博客图片修整中,看不了可以先搜索公众号“忘机山人”看。

https://appstore.lazycat.cloud/#/shop/detail/xu.deploy.elasticsearch

本章导读:本章将详细介绍 Elasticsearch 的核心概念,包括索引、文档、映射、分片、副本、集群和节点等,这些概念是理解和使用 Elasticsearch 的基础。

目录

索引(Index)

什么是索引

索引是 Elasticsearch 中存储数据的逻辑命名空间,类似于关系型数据库中的"数据库"概念。一个索引包含一组具有相似特征的文档。

索引命名规则

索引名称必须遵循以下规则:

  • 只能使用小写字母
  • 不能包含 \/*?"<>|、空格、逗号、#
  • 7.0 之前可以包含冒号 :,但已废弃
  • 不能以 -_+ 开头
  • 不能是 ...
  • 长度不能超过 255 字节

索引示例

// 创建索引
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:最大返回结果数
// 修改动态设置
PUT /products/_settings
{
  "index": {
    "number_of_replicas": 2,
    "refresh_interval": "30s"
  }
}

文档(Document)

什么是文档

文档是 Elasticsearch 中的基本数据单元,以 JSON 格式存储。每个文档都属于一个索引,并有一个唯一的 ID。

文档结构

一个文档包含以下元数据:

元数据说明
_index文档所属的索引
_id文档的唯一标识符
_source文档的原始 JSON 内容
_version文档版本号
_seq_no序列号,用于并发控制
_primary_term主分片任期号

文档操作示例

// 创建文档(指定 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
// 自动生成 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日期创建时间
objectJSON 对象嵌套属性
nested嵌套对象数组评论列表

特殊类型

类型说明
geo_point地理坐标点
geo_shape地理形状
ipIP 地址
completion自动补全
dense_vector稠密向量

映射示例

// 创建索引时定义映射
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 / falseboolean
整数long
浮点数double
日期格式字符串date
其他字符串text + keyword
对象object
数组取决于第一个元素
// 控制动态映射行为
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):主分片的复制,用于故障转移和读取负载均衡

分片配置

// 创建索引时指定分片数
PUT /products
{
  "settings": {
    "number_of_shards": 3,      // 主分片数(创建后不可修改)
    "number_of_replicas": 1     // 每个主分片的副本数(可动态修改)
  }
}

分片数量规划

经验法则

  • 单个分片大小建议在 10GB - 50GB 之间
  • 分片数 = 预计数据量 / 单分片大小
  • 考虑未来增长,但不要过度分片

过度分片的问题

  • 每个分片消耗资源(内存、文件句柄)
  • 搜索需要协调更多分片,增加开销
  • 集群状态膨胀
// 查看分片分布
GET /_cat/shards/products?v

副本(Replica)

什么是副本

副本是主分片的完整复制。每个主分片可以有零个或多个副本。

副本的作用

  1. 高可用:主分片所在节点故障时,副本可以提升为主分片
  2. 读取扩展:搜索请求可以在主分片或副本上执行,提高读取吞吐量
  3. 数据冗余:防止数据丢失

副本配置

// 修改副本数量
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🔴部分主分片未分配,数据不完整
// 查看集群健康状态
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
}

集群配置

# 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 实例。每个节点都有唯一的名称和角色。

节点角色

角色配置说明
Masternode.roles: [master]管理集群状态、索引创建删除、分片分配
Datanode.roles: [data]存储数据、执行 CRUD、搜索、聚合
Ingestnode.roles: [ingest]执行 Ingest Pipeline 预处理
Coordinatingnode.roles: []路由请求、合并结果(无特定角色)
MLnode.roles: [ml]执行机器学习任务
Remote Cluster Clientnode.roles: [remote_cluster_client]跨集群搜索

节点角色组合

# 专用主节点
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]

节点信息查看

// 查看所有节点
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关系型数据库说明
IndexDatabase数据的逻辑容器
MappingSchema数据结构定义
DocumentRow数据的基本单元
FieldColumn数据的属性
ShardPartition数据的物理分割

⚠️ 注意:这个对比仅用于帮助理解,ES 和关系型数据库的设计理念有本质区别。

本章小结

本章介绍了 Elasticsearch 的核心概念:

  1. 索引(Index):存储数据的逻辑命名空间,包含设置和映射
  2. 文档(Document):基本数据单元,JSON 格式,有唯一 ID
  3. 映射(Mapping):定义字段类型和索引方式,支持动态和显式映射
  4. 分片(Shard):索引的水平分割,实现分布式存储和并行处理
  5. 副本(Replica):主分片的复制,提供高可用和读取扩展
  6. 集群(Cluster):多节点协同工作,有 Green/Yellow/Red 三种状态
  7. 节点(Node):集群中的单个实例,可配置不同角色

理解这些概念是使用 Elasticsearch 的基础,后续章节将在此基础上深入讲解各个功能。

image.png

参考资料

评论

0

暂无评论

说点什么呢~
收藏
0
0
0