基础概念
- ES术语
- 【了解】es集群节点间的通信原理
- 断路器。
- 索引生命周期管理ilm 生产上配置的比较简单,数据没有分冷热,例如60天过后直接删除索引。在kibana上可以通过界面配置 极客时间ES中的视频对应章节75-76
- 重要的数据结构 文章:DocValue&fielddata 极客时间对应视频
重要的基础配置
es用root用户启动会报错,建议给es创建单独的用户
es默认network.host绑定是的本地回环localhost,这时候他默认你是用来测试的。不会启动bootstrap checks。但是当绑定的不是localhost时,会进行bootstrap checks,例如会检查虚拟内存有没有给够等等。如果配置没给够,会启动失败。不过日志中会说明那些配置没给够。参考官方文档:important-settings,system-config
GC不用关心,不用专门去调。而且jvm heap这块最多不要超过32G。我在生产上配置为31G。其实es使用的是大量的page cache,jvm heap的大小需要按需调整,不是越大越好,越大反而增加了GC的负担。
jdk配置
es包里带有一个官方测试过的open-jdk,在$ES_HOME/bin/elasticsearch-env中能看到选择jdk的地方。
# now set the path to java
if [ ! -z "$JAVA_HOME" ]; then
JAVA="$JAVA_HOME/bin/java"
else
if [ "$(uname -s)" = "Darwin" ]; then
# OSX has a different structure
JAVA="$ES_HOME/jdk/Contents/Home/bin/java"
else
JAVA="$ES_HOME/jdk/bin/java"
fi
fi
可以看到,如果操作系统里配置了java环境,会用操作系统里配置的。但是我们这里想用es包里面的。那么把这些都注释掉,留下这么一行就行
JAVA="$ES_HOME/jdk/Contents/Home/bin/java"
mapping
mapping规定了每个字段是什么数据类型,是否能分词(我们的业务不涉及),是否可搜索(我们的业务不涉及)
例如文本类型:在es中有text类型和keyword类型。 text涉及分词【不能聚合】,目前业务使用es做数据分析,所以字符类型的数据均应设置成keyword【可以聚合】。
通过动态mapping可以 将字符类型的 统一配置成keyword 还有些场景,例如我们想把int_xxx这种字段统一配置成int类型。 即int开头的字段名,在es中存为int。同理还有long_xxx。
template索引模板
template索引模板 对应极客时间ES视频 18-21节
每有一个新的业务时,创建索引必须好好设计索引模板。我接触到的索引模板中主要包含两部分,settings&mapping。附上一个demo:
# 通过kibana访问
GET _template/xxx-log
# 返回结果如下
{
"xxx-log" : {
"order" : 0,
# 模板就是一个模子,这些索引都能适用这个模板。所以是通配符。
"index_patterns" : [
"log-*"
],
"settings" : {
# 这里能够设置生命周期(我们都是用kibana可视化设置生命周期的),分片数量,副本数量。
"index" : {
"lifecycle" : {
"name" : "ilm-log"
},
"number_of_shards" : "1"
}
},
"mappings" : {
# 这里是动态模板,把所有文本类型的数据直接认为是keyword类型。因为我们的业务不涉及分词
"dynamic_templates" : [
{
"strings_as_keywords" : {
"mapping" : {
"type" : "keyword"
},
"match_mapping_type" : "string"
}
}
],
"properties" : {
"resp_time" : {
"type" : "integer"
},
"sequence" : {
"type" : "long"
},
"terminalNo" : {
"type" : "long"
},
# short占内存小,能省则省,因为是大数据。
"province" : {
"type" : "short"
},
"errCode" : {
"type" : "long"
},
"ip" : {
"type" : "ip"
},
# 时间类型的字段,需要和logstash洗出来的时间格式匹配,主要是后面要带时区
"snap_time" : {
"format" : [
"yyyy-MM-dd HH:mm:ss:SSSZ"
],
"type" : "date"
},
"index_date" : {
"type" : "date"
},
"logId" : {
"type" : "long"
},
"id" : {
"type" : "integer"
},
"attr" : {
"type" : "long"
}
}
},
# 别名 在复杂业务时好处多多。目前我们没有用到过。
"aliases" : { }
}
}
调优
根据经验,大的开源项目官方文档中都有详细的调优说明。es调优官方文档
es集群刚开始上线半个月后,频繁的出现fgc,发现fielddata占用了很多内存,并且不会被回收。由于用户频繁的对元数据_id进行排序操作,_id是text类型,对这种类型进行排序或者聚合就会导致出现这种情况。通过学习ES断路器相关知识,对fielddata阈值进行调整,限制为30%。
配置如下,需要重启集群才行。
indices.fielddata.cache.size: "30%"
如何查看fielddata使用情况。官方文档
用户访问控制
当v7.1时,简单的用户访问控制功能免费了。官方也出了文章以及视频。
es如何进行监控
通过kibana中monitor页面可以进行非常详细的底层指标观测。
如何进行预警:因为es提供了丰富的cat api。
目前做的监控预警比较简单,当集群的状态不是green时就发送邮件,检测频率为每分钟调用一次cat api (GET _cat/health)。
生产问题解决
- 当磁盘使用大小超过85%时,会停止写入。这时候咱们去清理一些磁盘空间,当磁盘空间释放后,还必须手动执行
PUT _settings
{
"index": {
"blocks": {
"read_only_allow_delete": "false"
}
}
}
- 极客时间上有专题讲解:65-74【阮一鸣ES课程】 这里面大部分咱们的生产环境都解决过,部分压测相关的没有做过。可以留意。
配置
es中的配置有的在线可以修改通过api,但是有些需要修改配置文件,滚动重启集群才可以。
配置分级别,有临时的,有永久的。需要注意,尽量不要使用cerebro去改配置。
滚动升级&滚动重启
背景:我们部署方式都是tar包。
滚动升级和重启最重要的是防止产生大量的IO。
es的升级不可逆,安排充分的时间进行升级操作,不要升了一半,剩下一般等明天再生。
官方建议
从数据节点开始升级,数据节点升级完成后再升级主节点。高版本的节点可以加入低版本的集群,反过来则不可以。要遵循这个规则。
Disable shard allocation.
这台节点都要下线进行升级了,默认一分钟后就会飘数据。不禁用会造成IO泛洪操作。
PUT _cluster/settings
{
"persistent": {
"cluster.routing.allocation.enable": "primaries"
}
}
通过下面的请求来验证,确认修改成功了。
GET _cluster/settings
如果开始发生分片的漂移了怎么取消?
这其实是分片的分布问题。官方文档,其中用过的是cancel取消分片的分配。
cancel Cancel allocation of a shard (or recovery). Accepts index and shard for index name and shard number, and node for the node to cancel the shard allocation on. This can be used to force resynchronization of existing replicas from the primary shard by cancelling them and allowing them to be reinitialized through the standard recovery process. By default only replica shard allocations can be cancelled. If it is necessary to cancel the allocation of a primary shard then the allow_primary flag must also be included in the request.
Stop non-essential indexing and perform a synced flush. (Optional)
滚动升级的时候有数据一直往里写入也是可以的,不过执行这个api会加速之后的恢复过程。具体描述参考官方文档
POST _flush/synced
这个api涉及的官方文档,里面提到v7.6之后被标记deprecate。
Shut down a single node.
停掉进程。不要kill -9 kill即可,观察日志看是否优雅停掉。
重点:准备要升级的包
包里的config,data,logs等相关配置需要留意。
其实就是把旧包里的配置挪到新版本的对应位置。
Start the upgraded node.
启动新版本的程序。
Reenable shard allocation.
恢复shard分配策略
PUT _cluster/settings
{
"persistent": {
"cluster.routing.allocation.enable": null
}
}
通过下面的请求来验证,确认恢复成功了。
GET _cluster/settings
Wait for the node to recover.
最后一步:可以在cerebro中观察是否集群健康状态为绿色
循环上述所有步骤,数据节点升级完成后再升级master节点

从7.2.0升7.6.1遇到的问题
deprecated日志出现
[WARN ][o.e.d.t.TransportInfo ] [node4] transport.publish_address was printed as [ip:port] instead of [hostname/ip:port]. This format is deprecated and will change to [hostname/ip:port] in a future version. Use -Des.transport.cname_in_publish_address=true to enforce non-deprecated formatting.
解决方案:加jvm参数。
# 在$ES_HOME/bin/elasticsearch这个脚本中添加
-Des.transport.cname_in_publish_address=true \
es启动输出大段内容
尚未有解决方案。github讨论说是一个bug。
regular expression has redundant nested repeat operator * /(?:(?:\[(?<TIMESTAMP_ISO8601:elasticsearch.server.timestamp>(?:(?>\d\d){1,2})-(?:(?:0?[1-9]|1[0-2]))-(?:(?:(?:0[1-9])|(?:[12][0-9])|(?:3[01])|[1-9]))[T ](?:(?:2[0123]|[01][0-9])):?(?:(?:[0-5][0-9]))(?::?(?:(?:(?:[0-5]?[0-9]|60)(?:[:.,][0-9]+)?)))?(?:(?:Z|[+-](?:(?:2[0123]|[01]?[0-9]))(?::?(?:(?:[0-5][0-9])))))?)\]\[(?<LOGLEVEL:log.level>([Aa]lert|ALERT|[Tt]race|TRACE|[Dd]ebug|DEBUG|[Nn]otice|NOTICE|[Ii]nfo|INFO|[Ww]arn?(?:ing)?|WARN?(?:ING)?|[Ee]rr?(?:or)?|ERR?(?:OR)?|[Cc]rit?(?:ical)?|CRIT?(?:ICAL)?|[Ff]atal|FATAL|[Ss]evere|SEVERE|EMERG(?:ENCY)?|[Ee]merg(?:ency)?))(?:\s*)?\]\[(?<DATA:elasticsearch.component>.*?)(?:\s*)\]((?:\s*))?(\[(?<DATA:elasticsearch.node.name>.*?)\])?((?:\s*))?)(?:\[gc\]\[(?<NUMBER:elasticsearch.server.gc.overhead_seq>(?:(?:(?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+))))))\] overhead, spent \[(?<NUMBER:elasticsearch.server.gc.collection_duration.time:float>(?:(?:(?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+))))))(?<DATA:elasticsearch.server.gc.collection_duration.unit>.*?)\] collecting in the last \[(?<NUMBER:elasticsearch.server.gc.observation_duration.time:float>(?:(?:(?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+))))))(?<DATA:elasticsearch.server.gc.observation_duration.unit>.*?)\]))|(?:(?:\[(?<TIMESTAMP_ISO8601:elasticsearch.server.timestamp>(?:(?>\d\d){1,2})-(?:(?:0?[1-9]|1[0-2]))-(?:(?:(?:0[1-9])|(?:[12][0-9])|(?:3[01])|[1-9]))[T ](?:(?:2[0123]|[01][0-9])):?(?:(?:[0-5][0-9]))(?::?(?:(?:(?:[0-5]?[0-9]|60)(?:[:.,][0-9]+)?)))?(?:(?:Z|[+-](?:(?:2[0123]|[01]?[0-9]))(?::?(?:(?:[0-5][0-9])))))?)\]\[(?<LOGLEVEL:log.level>([Aa]lert|ALERT|[Tt]race|TRACE|[Dd]ebug|DEBUG|[Nn]otice|NOTICE|[Ii]nfo|INFO|[Ww]arn?(?:ing)?|WARN?(?:ING)?|[Ee]rr?(?:or)?|ERR?(?:OR)?|[Cc]rit?(?:ical)?|CRIT?(?:ICAL)?|[Ff]atal|FATAL|[Ss]evere|SEVERE|EMERG(?:ENCY)?|[Ee]merg(?:ency)?))(?:\s*)?\]\[(?<DATA:elasticsearch.component>.*?)(?:\s*)\]((?:\s*))?(\[(?<DATA:elasticsearch.node.name>.*?)\])?((?:\s*))?)(?:\[gc\]\[young\]\[(?<NUMBER:elasticsearch.server.gc.young.one>(?:(?:(?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+))))))\]\[(?<NUMBER:elasticsearch.server.gc.young.two>(?:(?:(?<![0-9.+-])(?>[+-]?(?:(?:[0-9]+(?:\.[0-9]+)?)|(?:\.[0-9]+))))))\](?:\s*)(?<GREEDYMULTILINE:message>(.|
)*)))|(?:(?:\[(?<TIMESTAMP_ISO8601:elasticsearch.server.timestamp>(?:(?>\d\d){1,2})-(?:(?:0?[1-9]|1[0-2]))-(?:(?:(?:0[1-9])|(?:[12][0-9])|(?:3[01])|[1-9]))[T ](?:(?:2[0123]|[01][0-9])):?(?:(?:[0-5][0-9]))(?::?(?:(?:(?:[0-5]?[0-9]|60)(?:[:.,][0-9]+)?)))?(?:(?:Z|[+-](?:(?:2[0123]|[01]?[0-9]))(?::?(?:(?:[0-5][0-9])))))?)\]\[(?<LOGLEVEL:log.level>([Aa]lert|ALERT|[Tt]race|TRACE|[Dd]ebug|DEBUG|[Nn]otice|NOTICE|[Ii]nfo|INFO|[Ww]arn?(?:ing)?|WARN?(?:ING)?|[Ee]rr?(?:or)?|ERR?(?:OR)?|[Cc]rit?(?:ical)?|CRIT?(?:ICAL)?|[Ff]atal|FATAL|[Ss]evere|SEVERE|EMERG(?:ENCY)?|[Ee]merg(?:ency)?))(?:\s*)?\]\[(?<DATA:elasticsearch.component>.*?)(?:\s*)\]((?:\s*))?(\[(?<DATA:elasticsearch.node.name>.*?)\])?((?:\s*))?)(?:\s*)((\[(?<INDEXNAME:elasticsearch.index.name>[a-zA-Z0-9_.-]*)\]|\[(?<INDEXNAME:elasticsearch.index.name>[a-zA-Z0-9_.-]*)\/(?<DATA:elasticsearch.index.id>.*?)\]))?(?:\s*)(?<GREEDYMULTILINE:message>(.|
)*))/