一、ES配置项作用解析
1. 集群连接核心配置
es.hostlist
:定义ES集群的节点列表(domain:9200
等3个节点)。
作用:客户端通过这些节点连接集群,ES会自动发现集群拓扑,实现负载均衡(查询请求分散到不同节点)和故障转移(某节点宕机时自动切换到其他节点)。9200
是ES默认的HTTP通信端口。es.httpType=http
:指定连接协议为HTTP
(未加密)。
若集群启用SSL/TLS加密,需改为https
,并可能需要额外配置证书(如ssl.certificate
等)。es.username=elastic
和es.password=passwordXXXX
:
作用:ES的认证凭证。elastic
是内置超级管理员用户,通过HTTP Basic认证访问集群(需集群开启安全模块,如X-Pack Security)。生产环境建议创建权限更精细的专用用户(避免直接使用elastic
)。
2. 索引创建配置(es.settings.as
)
{"number_of_replicas":0, "number_of_shards":1}
number_of_shards:1
:每个索引的主分片数量为1。
主分片是数据存储的基本单元,决定索引的“水平扩展能力”(分片越多,可分散到更多节点存储)。此配置适合数据量较小的场景(单节点可承载)。number_of_replicas:0
:主分片的副本分片数量为0。
副本分片是主分片的冗余备份,作用是:① 故障恢复(主分片所在节点宕机时,副本可升级为主分片);② 分担查询压力。
风险:副本数为0时,若主分片所在节点故障,数据可能永久丢失(生产环境建议至少设置1个副本:number_of_replicas:1
)。
3. 索引映射配置(es.mappings.as
)
映射定义字段的类型、分词规则及功能(如是否支持聚合),核心字段解析:
{
"properties": {
"fs_ocode": { "type":"text", "fields":{"keyword":{"type":"keyword"}}, "fielddata":"true" },
"fs_atext": { "fielddata":"true", "analyzer":"ik_max_word", "type":"text" },
"fs_ctext": { "fielddata":"true", "analyzer":"ik_max_word", "type":"text" },
"fs_agentno": { "type":"keyword" },
"fs_extracttag": { "type":"keyword" },
"fs_bcode": { "type":"keyword" },
"fdt_cdate": { "type":"text", "fields":{"keyword":{"type":"keyword"}}, "fielddata":"true" },
"fdt_starttime": { "type":"keyword" },
"fdt_endtime": { "type":"keyword" },
"fdt_full_cdate": { "type":"keyword" }
}
}
text
类型(如fs_ocode
、fs_atext
):
用于全文检索,会被分词器处理。例如fs_atext
和fs_ctext
指定analyzer: "ik_max_word"
(IK分词器的“最细粒度分词”),支持中文文本拆分(如“客服服务”拆分为“客服、服务、客、服”等),适合中文搜索。keyword
子字段(如fs_ocode.keyword
):
text
字段默认不支持精确匹配、聚合或排序,通过fields.keyword
定义keyword
类型子字段,用于:① 精确匹配(如term
查询);② 聚合(如统计不同fs_ocode
的数量);③ 排序。keyword
类型(如fs_agentno
、fs_bcode
):
字段值不分词,直接作为整体存储,适合:① 唯一标识(如座席工号fs_agentno
);② 枚举值(如业务编码fs_bcode
);③ 时间字符串(如fdt_starttime
),支持精确匹配和聚合。fielddata:true
:
text
字段默认关闭fielddata
(避免占用内存),开启后允许对text
字段进行聚合/排序。但fielddata
会加载字段值到内存并构建缓存,风险:高频更新或大容量字段可能导致内存溢出。建议优先使用keyword
子字段(如用fs_ocode.keyword
聚合,而非fs_ocode
)。
4. 查询限制(es.limit.as=5000
)
作用:单次查询默认最大返回5000条文档,避免大量数据导致客户端内存溢出。如需更多数据,可通过分页(from
+size
)或滚动查询(scroll
)实现。
二、连接ES集群(基于配置)
需使用集群节点、协议、认证信息,以下是常用工具/语言的连接方式:
1. 命令行(curl)连接
# 测试集群健康状态(返回"status":"green"表示正常)
curl -u elastic:passwordXXXX "http://domain:9200/_cluster/health"
-u
:指定用户名和密码(elastic:密码
);- 连接任一节点即可(ES客户端会自动发现其他节点)。
- 地址格式:
http://{host}:{port}
(对应es.httpType
和es.hostlist
)。
2. Python(elasticsearch
库)连接
from elasticsearch import Elasticsearch
# 初始化客户端(自动负载均衡)
es = Elasticsearch(
hosts=[
"http://domain:9200",
"http://nlpaicc-2-prd-es.bdp.sfcloud.local:9200",
"http://nlpaicc-3-prd-es.bdp.sfcloud.local:9200"
],
basic_auth=("elastic", "passwordXXXX"), # 认证
timeout=30 # 超时时间(秒)
)
# 测试连接(返回True表示成功)
print(es.ping())
3. Java(High Level REST Client)连接
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.RestClientBuilder.HttpHost;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
// 配置认证
CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials("elastic", "passwordXXXX")
);
// 构建客户端
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("domain", 9200, "http"),
new HttpHost("nlpaicc-2-prd-es.bdp.sfcloud.local", 9200, "http"),
new HttpHost("nlpaicc-3-prd-es.bdp.sfcloud.local", 9200, "http")
).setHttpClientConfigCallback(httpClientBuilder ->
httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)
)
);
// 测试连接(无异常则成功)
client.info();
三、查询操作示例(基于映射)
假设目标索引为biz_index
,以下是典型查询场景:
1. 精确匹配(keyword
字段)
查询fs_bcode
为“000010”的文档:
# curl命令
curl -u elastic:passwordXXXX "http://domain:9200/biz_index/_search" -H "Content-Type: application/json" -d '
{
"query": { "term": { "fs_bcode": "000010" } }, # term查询keyword字段(精确匹配)
"size": 10 # 返回10条结果
}'
2. 中文全文检索(text
字段+IK分词)
查询fs_atext
中包含“客服”的文档:
# Python代码
response = es.search(
index="biz_index",
body={
"query": { "match": { "fs_atext": "客服" } } # match查询text字段(全文检索)
}
)
# 打印结果
for hit in response["hits"]["hits"]:
print(hit["_source"]) # 文档原始数据
3. 聚合统计(keyword
字段)
统计不同座席工号(fs_agentno
)的文档数量:
response = es.search(
index="biz_index",
body={
"size": 0, # 不返回文档,只返回聚合结果
"aggs": {
"agent_stats": { "terms": { "field": "fs_agentno" } } # 聚合keyword字段
}
}
)
# 打印聚合结果
print(response["aggregations"]["agent_stats"]["buckets"])
四、删除索引操作(谨慎执行)
删除索引会永久删除数据,步骤如下:
1. 命令行(curl)删除
# 1. 确认索引存在
curl -u elastic:passwordXXXX "http://domain:9200/biz_index"
# 2. 确认后删除(替换为目标索引名)
curl -u elastic:passwordXXXX -X DELETE "http://domain:9200/biz_index"
2. Python删除索引
# 检查索引是否存在
if es.indices.exists(index="biz_index"):
es.indices.delete(index="biz_index") # 删除索引
print("索引删除成功")
else:
print("索引不存在")
五、空索引风险分析
空索引的核心风险点:
- 元数据冗余:ES集群的master节点需要维护所有索引的元数据(映射、分片配置等),空索引会无意义地消耗元数据资源,尤其当空索引数量增多时,可能降低集群状态更新效率。
- 资源浪费:即使无数据,空索引仍会占用固定的分片资源(默认1主分片),若分片分配到数据节点,会占用节点的内存和文件描述符。
- 隐藏业务问题:空索引可能是“数据未正确写入”的信号(如程序bug、权限问题、索引名称配置错误等),若未及时处理,可能导致业务数据丢失或功能异常。
1. 核实空索引状态(确认是否真的为空及属性)
通过ES API查询索引的文档数量、创建时间、映射配置等,判断是否为“真·空索引”及是否有保留价值:
- 查看文档数:
GET /{index}/_count
(结果count:0
则为空) - 查看索引信息:
GET /{index}
(含创建时间、分片数、映射等) - 查看历史数据痕迹:
GET /{index}/_stats
(确认是否曾经有数据,因删除变为空)
2. 分类处理空索引
根据索引用途和业务确认结果,分三类处理:
(1)废弃索引(确认不再使用)
- 典型场景:测试残留(如
000003
、000007
这类数字索引)、业务下线后未清理的索引。 - 处理方式:安全删除,释放资源。
- 操作前备份映射(如需留存配置):
GET /{index}/_mapping
→ 保存结果。 - 删除命令:
DELETE /{index}
(生产环境建议先关闭索引POST /{index}/_close
,观察1-2天无影响后再删除)。
- 操作前备份映射(如需留存配置):
(2)临时空索引(计划使用但暂未写入数据)
- 典型场景:新业务准备上线的索引(如
kg_ft_company_reg_info~xianggang
、~aomen
、~taiwan
可能是按地区划分的公司注册信息索引,暂未同步数据)。 - 处理方式:标记管理+监控,避免长期空转。
- 标记索引:通过别名或索引元数据添加备注(如
PUT /{index}/_settings {"metadata": {"description": "待同步香港公司数据,预计2025-09月启用"}}
)。 - 定期监控:设置定时任务(如每周)检查是否有数据写入,若超过预期时间仍为空,触发告警排查原因。
- 标记索引:通过别名或索引元数据添加备注(如
(3)异常空索引(应写入数据但未成功)
- 典型场景:
sq_text_embedding_index
(文本嵌入索引,可能因数据处理程序故障未生成数据)、地区索引(如~xianggang
)因同步脚本错误导致数据未写入。 - 处理方式:排查写入链路,修复数据同步。
- 检查应用日志:查看数据写入ES的客户端日志(如Java/Python客户端),确认是否有连接失败、权限不足、索引名称写错(如大小写、特殊字符)等错误。
- 验证索引配置:确认索引映射是否与写入数据结构匹配(如字段类型不兼容会导致写入失败),可通过
GET /{index}/_mapping
对比写入数据格式。 - 测试写入:手动插入一条测试数据(如
POST /{index}/_doc { "test": "data" }
),验证是否成功,定位是否为索引本身的问题。
3. 建立预防机制(避免未来空索引泛滥)
- 规范索引创建流程:要求创建索引时必须注明用途、生命周期、负责人,禁止随意创建测试索引。
- 索引生命周期管理(ILM):为业务索引配置ILM策略,自动清理长期为空的索引(如“30天无数据则自动删除”)。
- 示例策略:
关联索引:PUT _ilm/policy/empty_index_cleanup { "policy": { "phases": { "hot": { "actions": {} }, "delete": { "min_age": "30d", "actions": { "delete": {} } } } } }
PUT /{index}/_settings {"index.lifecycle.name": "empty_index_cleanup"}
- 示例策略:
- 定期巡检:每周通过脚本(如Python调用ES API)扫描集群所有索引,筛选出空索引并通知负责人确认,形成闭环管理。