十年前我刚入行时,遇到一个头疼的问题:要在百万级商品数据中实现实时搜索。传统数据库的LIKE查询慢得让人崩溃,直到发现了Elasticsearch这个神器。它本质上是一个基于Lucene的分布式搜索引擎,但比原生Lucene简单易用得多。
举个实际例子:某电商平台原先用MySQL做商品搜索,每次查询要3-5秒。换成Elasticsearch后,同样的搜索请求能在200毫秒内返回,而且支持拼音搜索、错别字纠正等高级功能。这就是为什么现在从电商、日志分析到企业搜索,Elasticsearch几乎成了标配。
注意:虽然Elasticsearch常被简称为ES,但在生产环境配置时一定要写全称,避免与Elastic公司其他产品混淆。
传统数据库像一本按页码编排的书,要找到包含"手机"的内容得逐页翻查。而Elasticsearch用的是倒排索引——相当于给书做了本"关键词目录",记录每个词出现在哪些页面。当搜索"手机"时,直接查目录就能立即定位所有相关文档。
实测对比:在100万条商品数据中:
Elasticsearch的分布式架构是其高性能的关键。假设我们有个3节点集群:
这样即使一个节点宕机,数据也不会丢失,查询也能继续。我曾遇到一个坑:创建索引时没预先设置分片数,后期数据量暴增后不得不重建索引。建议根据数据量预估:
以Ubuntu 20.04为例,最新版Elasticsearch 8.x的安装步骤:
bash复制# 导入Elasticsearch GPG密钥
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
# 添加APT源
echo "deb https://artifacts.elastic.co/packages/8.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-8.x.list
# 安装
sudo apt update && sudo apt install elasticsearch
# 启动服务
sudo systemctl start elasticsearch
安装后验证:
bash复制curl -X GET "localhost:9200/?pretty"
应该看到包含版本信息的JSON响应。
修改/etc/elasticsearch/elasticsearch.yml时重点关注:
yaml复制cluster.name: my-application # 集群名,所有节点必须相同
node.name: node-1 # 节点唯一标识
network.host: 0.0.0.0 # 绑定IP
discovery.type: single-node # 单节点模式
xpack.security.enabled: true # 启用基础安全
内存调整(/etc/elasticsearch/jvm.options):
conf复制-Xms2g # 最小堆内存
-Xmx2g # 最大堆内存
重要:Xms和Xmx必须设置相同,避免运行时内存调整开销。生产环境建议不超过物理内存的50%。
创建带自定义分片的索引:
bash复制PUT /products
{
"settings": {
"number_of_shards": 3,
"number_of_replicas": 1,
"analysis": {
"analyzer": {
"pinyin_analyzer": {
"tokenizer": "my_pinyin"
}
}
}
},
"mappings": {
"properties": {
"name": { "type": "text", "analyzer": "ik_max_word" },
"price": { "type": "double" },
"tags": { "type": "keyword" }
}
}
}
几个实用命令:
GET /_cat/indices?vDELETE /productsPOST /products/_close插入数据(指定ID):
bash复制PUT /products/_doc/1
{
"name": "华为Mate50 Pro",
"price": 6999.00,
"tags": ["手机", "5G", "旗舰"]
}
批量插入(性能关键):
bash复制POST /products/_bulk
{"index":{"_id":"2"}}
{"name":"iPhone 14","price":5999.00,"tags":["手机","iOS"]}
{"index":{"_id":"3"}}
{"name":"小米12S Ultra","price":6499.00,"tags":["手机","安卓"]}
复杂查询示例:
bash复制GET /products/_search
{
"query": {
"bool": {
"must": [
{ "match": { "name": "手机" } }
],
"filter": [
{ "range": { "price": { "gte": 5000 } } }
]
}
},
"sort": [
{ "price": { "order": "desc" } }
],
"highlight": {
"fields": {
"name": {}
}
}
}
在高写入场景下(如日志采集),我总结的配置组合:
json复制PUT /logs
{
"settings": {
"refresh_interval": "30s",
"number_of_replicas": 0,
"translog.durability": "async"
}
}
写入时禁用刷新:
bash复制POST /logs/_doc?refresh=false
{"message":"system start"}
批量提交能提升10倍以上吞吐量。实测对比:
json复制"price": {
"type": "double",
"doc_values": true
}
json复制"query": {
"term": {
"user.id": {
"value": "kimchy",
"boost": 1.0
}
}
}
bash复制# 不好的做法
GET /_search?from=10000&size=10
# 推荐方案
GET /_search
{
"size": 10,
"search_after": [last_sort_value]
}
根据多年运维经验,不同场景的配置推荐:
| 场景 | CPU核心 | 内存 | 磁盘类型 | 节点数 |
|---|---|---|---|---|
| 开发测试 | 4-8 | 8-16G | SSD | 1 |
| 中小型搜索 | 16-32 | 32-64G | NVMe SSD | 3-5 |
| 日志分析 | 32+ | 64G+ | 高吞吐HDD | 5+ |
| 企业级搜索 | 64+ | 128G+ | 高性能NVMe | 7+ |
症状:集群状态变红
GET /_cluster/healthbash复制PUT /_cluster/settings
{
"persistent": {
"cluster.routing.allocation.enable": "all"
}
}
症状:查询超时
GET /_nodes/hot_threads?timeout=2m"preference": "_local"症状:磁盘空间不足
bash复制PUT /_all/_settings
{
"index.blocks.read_only_allow_delete": null
}
安装后访问http://localhost:5601,几个实用功能:
典型日志处理配置:
conf复制input {
file {
path => "/var/log/nginx/access.log"
start_position => "beginning"
}
}
filter {
grok {
match => { "message" => "%{COMBINEDAPACHELOG}" }
}
date {
match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
}
}
output {
elasticsearch {
hosts => ["localhost:9200"]
index => "nginx-%{+YYYY.MM.dd}"
}
}
Filebeat配置示例:
yaml复制filebeat.inputs:
- type: log
paths:
- /var/log/*.log
output.elasticsearch:
hosts: ["localhost:9200"]
indices:
- index: "syslog-%{+yyyy.MM.dd}"
掌握基础后,建议按这个顺序深入:
推荐的学习资源:
我在实际项目中最大的体会是:Elasticsearch虽然开箱即用,但要真正发挥威力,必须根据业务特点精心设计索引结构和查询方式。比如电商搜索需要重点优化相关性评分,而日志分析则要关注存储效率和聚合性能。