1. 引言
本文档详细介绍如何使用Docker部署单节点Elasticsearch 9.1.0(2025年最新稳定版)并配置索引存储压缩功能。Elasticsearch 9.1.0带来了多项性能优化和安全增强,包括改进的内存管理和全新的Entitlements权限系统。通过启用best_compression
压缩模式,可将索引存储大小减少约40%,显著降低存储成本。
2. 环境准备
2.1 安装Docker
确保您的系统已安装Docker 20.10.10或更高版本:
# Ubuntu/Debian示例
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
2.2 配置系统参数
Elasticsearch需要调整系统内核参数:
# 临时设置(立即生效)
sudo sysctl -w vm.max_map_count=262144
# 永久设置(重启后生效)
echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf
2.3 配置Docker镜像加速器(可选)
为加快镜像拉取速度,配置国内镜像源:
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors":
[
"https://2l1bnhmy.mirror.aliyuncs.com",
"https://hub.littlediary.cn",
"https://hub.xdark.top",
"https://docker.nastool.de",
"https://docker.m.daocloud.io",
"https://cr.console.aliyun.com/",
"https://dockerhub.icu"
]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
3. Docker部署Elasticsearch
3.1 创建专用网络
docker network create elastic-net
3.2 拉取官方镜像
docker pull docker.elastic.co/elasticsearch/elasticsearch:9.1.0
3.3 运行单节点容器
# 创建本地数据目录并设置权限
mkdir -p /data/elasticsearch/{data,logs,plugins}
sudo chown -R 1000:0 /data/elasticsearch
# 启动容器
docker run -d \
--name es01 \
--net elastic-net \
-p 9200:9200 \
-e "discovery.type=single-node" \
-e "ES_JAVA_OPTS=-Xms1g -Xmx1g" \
-e "xpack.security.enabled=false" \
-v /data/elasticsearch/data:/usr/share/elasticsearch/data \
-v /data/elasticsearch/logs:/usr/share/elasticsearch/logs \
-v /data/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
--restart=always \
docker.elastic.co/elasticsearch/elasticsearch:9.1.0
3.4 验证部署
# 检查容器状态
docker ps | grep es01
# 验证Elasticsearch运行状态
curl http://localhost:9200
成功响应示例:
{
"name" : "es01",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "xxxxxxxxxxxx",
"version" : {
"number" : "9.1.0",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "xxxxxx",
"build_date" : "2025-07-29T04:20:00.000Z",
"build_snapshot" : false,
"lucene_version" : "10.2.2",
"minimum_wire_compatibility_version" : "8.13.0",
"minimum_index_compatibility_version" : "8.0.0"
},
"tagline" : "You Know, for Search"
}
如果是ubuntu可以参考上面的部署docker,我用的rocky8,可以参考下面的文档部署docker,没问题就继续看 4. 配置索引压缩
2.1 针对Rocky Linux 8的额外配置
如果您使用的是Rocky Linux 8系统,请按照以下步骤安装Docker:
2.1.1 卸载冲突组件
Rocky Linux默认安装Podman,需要先卸载以避免冲突:
sudo dnf remove podman buildah -y
2.1.2 安装Docker依赖
sudo dnf update -y
sudo dnf install -y yum-utils device-mapper-persistent-data lvm2
2.1.3 添加Docker仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
2.1.4 安装Docker
sudo dnf install -y docker-ce docker-ce-cli containerd.io
2.1.5 配置防火墙
# 开放9200端口
sudo firewall-cmd --add-port=9200/tcp --permanent
sudo firewall-cmd --reload
2.1.6 SELinux配置(可选)
临时关闭SELinux(立即生效):
sudo setenforce 0
永久关闭SELinux(需重启):
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
2.1.7 启动Docker服务
sudo systemctl start docker
sudo systemctl enable docker
注意:Rocky Linux 8的后续步骤(如运行容器、配置Elasticsearch)与Ubuntu系统一致,继续按照文档后续章节操作即可
4. 配置索引压缩
4.1 创建索引时启用压缩(不推荐,看下面那个)
# 使用curl创建带压缩配置的索引
curl -X PUT "http://localhost:9200/my_compressed_index" -H 'Content-Type: application/json' -d'
{
"settings": {
"index.codec": "best_compression",
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"properties": {
"message": { "type": "text" },
"timestamp": { "type": "date" }
}
}
}
'
4.2 创建全局索引模板(推荐)
为所有新索引自动启用压缩:(注意:请求里面的注释在执行时需要去掉,不然会报错)
curl -X PUT "http://localhost:9200/_template/compression_template" -H 'Content-Type: application/json' -d'
{
"index_patterns": ["*"], // 匹配所有索引
"order": 1,
"settings": {
"index.codec": "best_compression"
}
}
'
注意:模板仅对创建后新索引生效,现有索引需重建才能应用压缩配置。
5. 验证压缩效果
5.1 检查索引配置
curl "http://localhost:9200/my_compressed_index/_settings?pretty"
应看到以下配置:
{
"my_compressed_index" : {
"settings" : {
"index" : {
"codec" : "best_compression",
...
}
}
}
}
5.2 比较压缩效果
# 查看索引大小
curl "http://localhost:9200/_cat/indices?v"
索引名称 | 状态 | 文档数 | 存储大小 |
---|---|---|---|
my_compressed_index | open | 10000 | 2.1mb |
my_default_index | open | 10000 | 3.5mb |
使用best_compression
的索引通常比默认配置小40-50%。
6. 注意事项
6.1 生产环境配置
生产环境应启用安全功能:
# 生产环境启动命令(示例)
docker run -d \
--name es01 \
--net elastic-net \
-p 9200:9200 \
-e "discovery.type=single-node" \
-e "ES_JAVA_OPTS=-Xms4g -Xmx4g" \
-e "xpack.security.enabled=true" \
-e "ELASTIC_PASSWORD=StrongPassword123!" \
...(其他参数同上)
6.2 性能影响
- 写入性能:可能降低约10-15%
- 查询性能:复杂查询可能增加5-10%延迟
- 存储节省:通常可减少40-60%存储空间
6.3 数据备份
定期备份数据目录:
tar -czf es_backup_$(date +%Y%m%d).tar.gz /data/elasticsearch/data
7. 常见问题排查
7.1 容器启动失败
# 查看日志
docker logs es01
# 常见原因:
# 1. 内存不足:调整ES_JAVA_OPTS
# 2. 权限问题:检查/data/elasticsearch目录权限
# 3. 端口占用:使用netstat -tulpn | grep 9200检查端口
7.2 压缩配置不生效
- 确认索引是在模板创建后新建的
- 检查模板是否匹配索引名称(index_patterns)
- 对于现有索引,需重建索引:
# 重建索引示例
curl -X POST "http://localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
"source": { "index": "old_index" },
"dest": { "index": "new_index_with_compression" }
}
'
8. 总结
通过Docker部署单节点Elasticsearch 9.1.0并启用best_compression
索引压缩,可在测试/开发环境中显著节省存储空间。生产环境中建议结合实际业务需求评估压缩带来的存储节省与性能影响,并务必启用安全功能和数据备份策略。
。## 8. 常见问题解决:Docker仓库安装失败
8.1 问题现象
安装Docker时出现以下错误:
GPG error: https://download.docker.com/linux/centos docker-ce-stable InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 7EA0A9C3F273FCD8
或
Error: Failed to download metadata for repo 'docker-ce-stable': Cannot download repomd.xml: Cannot download repodata/repomd.xml: All mirrors were tried
8.2 解决方案
方法一:使用阿里云镜像源(推荐,rocky8系统)
移除现有Docker仓库配置:
sudo rm -f /etc/yum.repos.d/docker-ce.repo
添加阿里云Docker仓库:
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
修正仓库版本变量(Rocky Linux专用):
sudo sed -i 's/$releasever/8/g' /etc/yum.repos.d/docker-ce.repo
安装Docker:
sudo dnf install docker-ce docker-ce-cli containerd.io -y
方法二:手动解决GPG密钥问题
下载Docker官方GPG密钥:
curl -fsSL https://download.docker.com/linux/centos/gpg -o docker-gpg.key
导入密钥:
sudo rpm --import docker-gpg.key
验证密钥导入:
rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' | grep Docker
重新安装Docker:
sudo dnf install docker-ce docker-ce-cli containerd.io -y
方法三:离线安装(适用于无网络环境)
下载离线RPM包(需从有网络环境获取):
本地安装:
sudo dnf localinstall *.rpm -y
8.3 验证安装
# 启动Docker服务
sudo systemctl start docker
sudo systemctl enable docker
# 验证Docker版本
docker --version
# 运行测试容器
docker run hello-world
8.4 额外系统配置
防火墙设置
sudo firewall-cmd --add-port=9200/tcp --permanent
sudo firewall-cmd --reload
SELinux配置(可选)
# 临时关闭(立即生效)
sudo setenforce 0
# 永久关闭(需重启)
sudo sed -i 's/SELINUX=enforcing/SELINUX=permissive/g' /etc/selinux/config
通过以上方法可解决99%的Docker仓库安装失败问题,若仍有异常,请检查网络连接或尝试更换网络环境。
9. 索引模板管理:删除压缩配置
9.1 删除索引模板
要删除之前创建的compression_template
索引模板,执行以下命令:
curl -X DELETE "http://localhost:9200/_template/compression_template"
成功删除后,Elasticsearch将返回:
{
"acknowledged": true
}
9.2 验证模板删除结果
检查特定模板是否存在
curl "http://localhost:9200/_template/compression_template"
如果模板已成功删除,将返回:
{
"found": false
}
列出所有索引模板(可选)
curl "http://localhost:9200/_template?pretty"
9.3 对现有索引的影响
- 已创建的索引:保持原有的
best_compression
压缩配置,不受模板删除影响 - 新创建的索引:将使用默认压缩算法(LZ4),不再应用
best_compression
9.4 如何移除现有索引的压缩配置
如果需要将已存在的索引恢复为默认压缩(LZ4),需通过重建索引实现:
步骤1:创建临时索引(使用默认压缩)
(注意:请求里面的注释在执行时需要去掉,不然会报错)
curl -X PUT "http://localhost:9200/temp_index" -H 'Content-Type: application/json' -d'
{
"settings": {
"index.codec": "default", // 使用默认LZ4压缩
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"properties": {
// 复制原索引的映射定义
"message": { "type": "text" },
"timestamp": { "type": "date" }
}
}
}'
步骤2:迁移数据到临时索引
curl -X POST "http://localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
"source": { "index": "original_index" },
"dest": { "index": "temp_index" }
}'
步骤3:替换原索引
# 删除原索引(请确保数据已迁移完成)
curl -X DELETE "http://localhost:9200/original_index"
# 重建原索引(使用默认压缩)(注意:请求里面的注释在执行时需要去掉,不然会报错)
curl -X PUT "http://localhost:9200/original_index" -H 'Content-Type: application/json' -d'
{
"settings": {
"index.codec": "default"
},
"mappings": {
"properties": {
// 与临时索引相同的映射定义
"message": { "type": "text" },
"timestamp": { "type": "date" }
}
}
}'
# 将数据迁移回原索引
curl -X POST "http://localhost:9200/_reindex" -H 'Content-Type: application/json' -d'
{
"source": { "index": "temp_index" },
"dest": { "index": "original_index" }
}'
# 删除临时索引
curl -X DELETE "http://localhost:9200/temp_index"
9.5 带认证的操作(如启用了安全功能)
如果Elasticsearch启用了用户名密码认证,需在curl命令中添加-u
参数:
# 删除模板示例
curl -u elastic:your_password -X DELETE "http://localhost:9200/_template/compression_template"
# 验证示例
curl -u elastic:your_password "http://localhost:9200/_template/compression_template"
通过以上步骤,您可以彻底删除索引模板并根据需要调整现有索引的压缩配置。
10. 压缩模板效果验证方法,开始验证了(验证best_compression的效果)
10.1 测试环境准备
10.1.1 清理环境(可选)
# 删除之前的测试索引(如有)
curl -X DELETE "http://localhost:9200/index_without_compression"
curl -X DELETE "http://localhost:9200/index_with_compression"
# 确保压缩模板状态(按需操作)
curl -X DELETE "http://localhost:9200/_template/compression_template"
10.1.2 创建测试数据生成脚本
创建generate_test_data.py
:
创建10万条重复模式测试数据,数据量太小看不出效果
python3.6 -c "import json; print('\n'.join([json.dumps({'index':{}}) + '\n' + json.dumps({
'message': '重复日志模式: 用户登录失败',
'category': f'category_{i%10}',
'timestamp': f'2025-08-06T{i%24:02d}:{i%60:02d}:{i%60:02d}Z',
'value': i
}) for i in range(100000)]))" > large_test_data.json
10.2 无压缩模板场景测试
10.2.1 创建无压缩索引
(注意:请求里面的注释在执行时需要去掉,不然会报错)
curl -X PUT "http://localhost:9200/index_without_compression" -H 'Content-Type: application/json' -d'
{
"settings": {
"index.codec": "default", // 使用默认LZ4压缩
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"properties": {
"message": { "type": "text" },
"timestamp": { "type": "date" },
"value": { "type": "integer" },
"category": { "type": "keyword" },
"tags": { "type": "keyword" }
}
}
}'
10.2.2 写入测试数据
curl -X POST "http://localhost:9200/index_without_compression/_bulk" \
-H "Content-Type: application/json" \
--data-binary @large_test_data.json
10.2.3 强制合并分段
# 强制合并为单个分段(确保大小统计准确)
curl -X POST "http://localhost:9200/index_without_compression/_forcemerge?max_num_segments=1"
10.2.4 记录索引大小(可选,因为直接查看索引就能看出大小)
# 获取索引统计信息
curl "http://localhost:9200/index_without_compression/_stats?human&pretty" > without_compression_stats.json
# 提取存储大小
jq -r '.indices.index_without_compression.total.store.size' without_compression_stats.json
10.3 有压缩模板场景测试
10.3.1 创建压缩模板
curl -X PUT "http://localhost:9200/_template/compression_template" -H 'Content-Type: application/json' -d'
{
"index_patterns": ["index_with_compression*"],
"order": 1,
"settings": {
"index.codec": "best_compression",
"number_of_shards": 1,
"number_of_replicas": 0
}
}'
10.3.2 创建应用模板的索引
# 索引名称需匹配模板的index_patterns
curl -X PUT "http://localhost:9200/index_with_compression"
10.3.3 写入相同测试数据
curl -X POST "http://localhost:9200/index_with_compression/_bulk" \
-H "Content-Type: application/json" \
--data-binary @large_test_data.json
10.3.4 强制合并分段
curl -X POST "http://localhost:9200/index_with_compression/_forcemerge?max_num_segments=1"
10.3.5 记录索引大小(可选,因为直接查看索引就能看出大小)
# 获取索引统计信息
curl "http://localhost:9200/index_with_compression/_stats?human&pretty" > with_compression_stats.json
# 提取存储大小
jq -r '.indices.index_with_compression.total.store.size' with_compression_stats.json
10.4 压缩效果对比分析(可选,查看索引后直接除一下)
10.4.1 计算压缩率
# 提取数值进行计算(假设单位为MB)
WITHOUT_SIZE=$(grep -oP '"size": "\K\d+\.\d+' without_compression_stats.json | head -1)
WITH_SIZE=$(grep -oP '"size": "\K\d+\.\d+' with_compression_stats.json | head -1)
# 计算压缩率
COMPRESSION_RATIO=$(echo "scale=2; (1 - $WITH_SIZE / $WITHOUT_SIZE) * 100" | bc)
echo "压缩率: $COMPRESSION_RATIO%"
10.4.2 典型结果示例
场景 | 索引大小 | 压缩率 | 查询延迟(match_all) |
---|---|---|---|
无压缩(LZ4) | 2.3 MB | - | 8ms |
有压缩(DEFLATE) | 1.3 MB | 39.1% | 11ms |
上面是官方测试的,下面这个结果是我自己测试的
[root@localhost ~]# curl http://localhost:9200/_cat/indices
green open index_without_compression EwA5_nhlR-SnDmakvsizNQ 1 0 100000 0 4mb 4mb 4mb
green open index_with_compression paSVgDTgRwGKDZfNnKw5gw 1 0 100000 0 2.4mb 2.4mb 2.4mb
压缩和不压缩的比率是:2.4:4,差不多就是40%,很可以了
10.4.3 结果解读
- 存储节省:
best_compression
通常比默认压缩节省30%-40%存储空间 - 性能影响:查询延迟可能增加5%-15%,写入性能影响较小
- 适用场景:推荐用于日志、归档等写入密集且查询频率低的数据
10.5 性能对比测试(可选)
10.5.1 查询性能测试
# 测试简单查询性能
echo "无压缩索引查询延迟:"
time curl -s -X POST "http://localhost:9200/index_without_compression/_search" -d'{"query":{"match_all":{}}}' > /dev/null
echo "有压缩索引查询延迟:"
time curl -s -X POST "http://localhost:9200/index_with_compression/_search" -d'{"query":{"match_all":{}}}' > /dev/null
# 测试复杂查询性能(带聚合)
echo "无压缩索引聚合查询:"
time curl -s -X POST "http://localhost:9200/index_without_compression/_search" -d'
{
"size": 0,
"aggs": {
"categories": {
"terms": { "field": "category", "size": 10 }
}
}
}' > /dev/null
echo "有压缩索引聚合查询:"
time curl -s -X POST "http://localhost:9200/index_with_compression/_search" -d'
{
"size": 0,
"aggs": {
"categories": {
"terms": { "field": "category", "size": 10 }
}
}
}' > /dev/null
10.6 清理测试环境
# 删除测试索引和模板
curl -X DELETE "http://localhost:9200/index_without_compression"
curl -X DELETE "http://localhost:9200/index_with_compression"
curl -X DELETE "http://localhost:9200/_template/compression_template"
# 删除测试数据文件
rm large_test_data.json without_compression_stats.json with_compression_stats.json
通过以上步骤,您可以科学验证压缩模板的实际效果,为生产环境配置提供数据支持。建议在实际应用前,使用与生产环境类似的数据和查询模式进行测试。
10.7 常见问题排查
JSON结构验证
# 检查存储大小字段路径
cat without_compression_stats.json | grep -A 10 '"store"'
正确输出应包含:
"store": {
"size": "2.3mb",
"size_in_bytes": 2411724,
"reserved": "0b",
"reserved_in_bytes": 0
}
API响应延迟处理
Elasticsearch缓存统计信息,强制刷新:
curl -X POST "http://localhost:9200/index_without_compression/_refresh"
curl -X POST "http://localhost:9200/index_with_compression/_refresh"
通过以上方法,可可靠提取存储大小并计算压缩率。推荐优先使用jq
工具,其对JSON结构的解析能力更强大,尤其适合自动化脚本场景。
10.8 压缩反膨胀现象处理
10.8.1 现象原因分析
当启用best_compression
后索引体积反而增大,主要由以下原因导致:
数据特性问题:
- 数据量不足:文档数量少于10,000条时,DEFLATE算法的压缩收益无法抵消元数据开销。官方测试表明,最佳压缩效果需10万+重复模式文档(如日志、监控数据)
- 内容随机性高:无重复字段值的随机数据会导致DEFLATE字典压缩失效,甚至比LZ4体积更大
索引存储机制:
- 多分段元数据叠加:未强制合并时,多个分段(segment)的元数据独立存储,总大小叠加
- 块对齐损耗:DEFLATE使用60KB块压缩,小数据无法填满块大小导致空间浪费
操作配置问题:
- 索引配置不一致:压缩索引可能包含更多字段或不同分片数
- 统计时机不当:后台段合并未完成时统计,捕捉到中间状态
10.8.2 生产环境建议
- 适用场景:日志、监控、时序数据等重复模式数据
- 数据规模:单索引文档数建议>10万,单分片大小>1GB
- 最佳实践:
- 结合ILM(索引生命周期管理)在温阶段启用压缩
- 压缩前执行
_forcemerge
减少分段数量 - 对随机数据或小索引保持默认LZ4压缩
通过以上步骤,可有效解决压缩反膨胀问题,并在生产环境中获得40-60%的存储节省。