Tips
ELK 使用小技巧(第 5 期)
Elasticsearch • rochy 发表了文章 • 0 个评论 • 6030 次浏览 • 2019-02-22 12:24
ELK Tips 主要介绍一些 ELK 使用过程中的小技巧,内容主要来源为 Elastic 中文社区。
一、Logstash
1、Logstash 性能调优主要参数
pipeline.workers
:设置启动多少个线程执行 fliter 和 output;当 input 的内容出现堆积而 CPU 使用率还比较充足时,可以考虑增加该参数的大小;pipeline.batch.size
:设置单个工作线程在执行过滤器和输出之前收集的最大事件数,较大的批量大小通常更高效,但会增加内存开销。输出插件会将每个批处理作为一个输出单元。;例如,ES 输出会为收到的每个批次发出批量请求;调整pipeline.batch.size
可调整发送到 ES 的批量请求(Bulk)的大小;pipeline.batch.delay
:设置 Logstash 管道的延迟时间, 管道批处理延迟是 Logstash 在当前管道工作线程中接收事件后等待新消息的最长时间(以毫秒为单位);简单来说,当pipeline.batch.size
不满足时,会等待pipeline.batch.delay
设置的时间,超时后便开始执行 filter 和 output 操作。
2、'reader' unacceptable character ' ' (0x0)
logstash 执行使用 Jdbc input plugin
后报错:
[main]-pipeline-manager] ERROR logstash.agent - Pipeline aborted due to error {
:exception=>#<Psych::SyntaxError: (): 'reader' unacceptable character ' ' (0x0) special characters are not allowed in "'reader'",
position 0 at line 0 column 0>, :backtrace=>["org/jruby/ext/psych/PsychParser.java:232:in parse'"
解决方案:删除 $USER_HOME/.logstash_jdbc_last_run
文件即可。
二、Elasticsearch
1、TermsQuery 与多个 TermQuery 的区别
当 terms 的个数较少的时候,TermsQuery 等效为 ConstantScoreQuery 内部包含多个 TermQuery:
Query q1 = new TermInSetQuery(new Term("field", "foo"), new Term("field", "bar"));
// 等效为下面的语句
BooleanQuery bq = new BooleanQuery();
bq.add(new TermQuery(new Term("field", "foo")), Occur.SHOULD);
bq.add(new TermQuery(new Term("field", "bar")), Occur.SHOULD);
Query q2 = new ConstantScoreQuery(bq);
当 terms 较多的时候,它将使用匹配的文档组合成一个位集,并在该位集上进行评分;此时查询效率比普通的 Bool 合并要更加高效。
当 terms 的个数较多时,TermsQuery 比多个 TermQuery 组合的查询效率更高。
2、ES 借助 nginx 配置域名
upstream /data/ {
server 192.168.187.xxx:9200;
keepalive 300 ;
}
server {
listen 80;
server_name testelk.xx.com;
keepalive_timeout 120s 120s;
location /data {
proxy_pass http://data/;
proxy_http_version 1.1;
proxy_set_header Connection "Keep-Alive";
proxy_set_header Proxy-Connection "Keep-Alive";
proxy_set_header X-Real-IP $remote_addr;
proxy_pass_header remote_user
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxy true;
}
}
3、ES Reindex 时如何不停止写入服务
方案一:kennywu76
ES 的 reindex 在索引有实时的 update/delete 的情况下,即使借助 alias,也没有办法实现真正的 zero down time。
增加新文档比较好办,通过 alias 切换写入到新索引,同时 reindex 做旧->新索引的数据传输即可;但是 update/delete 操作针对的文档如果还未从旧索引传输过来,直接对新索引操作会导致两个索引数据不一致。
我能够想到的(一个未经实际验证)的方案,前提是数据库里的文档有一个类似 last_update_time
字段记录文档最后更新的时间,用作写入 ES 文档的版本号,然后数据写入新索引的时候,url 里带上下面这样的参数:version_type=external_gt&version=xxxxxx
。
其中 version_type=external_gt
表示写入文档的版本号大于已有的文档版本号,或者文档不存在,写入才会成功,否则会抛版本冲突的异常。另外 delete 操作都要转换成 index 操作,index 的内容可以是一个空文档。
这样实时数据写入新索引和 reindex 可以同时进行,实时写入的数据应该具有更高的版本,总是能够成功,reindex 如果遇到版本冲突,说明该文档被实时部分更新过了,已经过时,可以直接放弃跳过。
该方案的缺陷:
- 要求数据源里的数据具有版本信息,可能因为各种局限,不太容易更改;
- delete 操作必须转化为写入一个空文档,delete 实际上是一个标记文档,并且本身也有版本信息。但是如果后端发生了 segment merge,delete 可能会被合并以后物理清除。这样 delete 和对应的版本信息丢失,之后 reindex 如果写入了旧版本的文档,仍然会有一致性问题;但是空文档会增加索引文件的大小,有额外的消耗,一个可能的缓解办法是在 reindex 全部做完以后,再做一次空文档的删除。
改进方案:the_best
重建索引步骤如下:
- 保证 delete 操作都要转换成 index 操作,index 的内容可以是一个空文档;
- 对老索引
old_index
(业务上的别名还是挂在老索引上)进行重索引操作(version_type=external
);curl -X POST 'http://<hostname>:9200/_reindex' { "conflicts": "proceed", "source": { "index": "old_index", "size": 1000 }, "dest": { "index": "new_index", "version_type": "external" } }
- 将别名切到 newIndex;
- 将重索引时间段内
old_index
产生的热数据,再捞一次到new_index
中(conflicts=proceed&version_type=external
);curl -X POST /_reindex { "conflicts": "proceed", "source": { "index": "old_index" "query": { "constant_score" : { "filter" : { "range" : { "data_update_time" : { "gte" : <reindex开始时刻前的毫秒时间戳> } } } } } }, "dest": { "index": "new_index", "version_type": "external" } }
- 手动做一次空文档的删除。
这种方式取决于重索引期间产生的数据量大小(会影响步骤4的用时),不过我们可以视具体业务情况灵活操作。比如说数据量比较大重索引我们用了10个小时(这10个小时内新产生了200多万的数据),在切别名前,我们可以按步骤(4)的调用方式,把近10个小时的数据再捞一遍到新索引中,如此迭代个几次,直到别名切完后,我们能保证最后一次的步骤(4)可以在较短时间内完成。
4、ES 节点通讯配置
http.port: 9200
http.bind_host: 127.0.0.1
transport.tcp.port: 9300
transport.bind_host: 127.0.0.1
5、把 Lucene 的原生 query 传给 ES
SearchRequest searchRequest = new SearchRequest(indexName);
searchRequest.types(typeName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.from(0);
sourceBuilder.size(10);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//q为Lucene检索表达式, 直接输入关键词匹配_all或者*字段, 字段匹配user:kimchy,
//多字段匹配user:kimchy AND message:Elasticsearch
QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(q);
sourceBuilder.query(queryStringQueryBuilder);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
SearchHits searchHits = searchResponse.getHits();
6、ES 文档字段个数限制
ES 文档默认不允许文档字段超过 1000,超过 1000 会报如下错误:
failed to put mappings on indices [[[nfvoemspm/srjL3cMMRUqa7DgOrYqX-A]]], type [log]
java.lang.IllegalArgumentException: Limit of total fields [1000] in index [xxx] has been exceeded
可以通过修改索引配置来修改字段个数限制,不过还是推荐从业务上进行优化:
修改settings
{
"index.mapping.total_fields.limit": 2000
}
7、将 DSL 字符串转换为 QueryBuilder
## wrapper 案例
GET /_search
{
"query" : {
"wrapper": {
"query" : "eyJ0ZXJtIiA6IHsgInVzZXIiIDogIktpbWNoeSIgfX0="
}
}
}
## RestClient
QueryBuilders.wrapperQuery("{\"term\": {\"field\":\"value\"}}")
8、ES 集群重启后 Slice Scroll 速度变慢
重启机器之后,pagecache 都没有了,所有数据都要重新从磁盘加载。
9、ES 开启索引新建删除日志
PUT _cluster/settings
{
"persistent": {
"logger.cluster.service": "DEBUG"
}
}
10、慢日志全局级别设定
- 对已经存在的索引可以通过 PUT _settings 做存量设置
- 对之后新增的索引,可以使用类似于下面的template
PUT _template/global-slowlog_template { "order": -1, "version": 0, "template": "*", "settings": { "index.indexing.slowlog.threshold.index.debug" : "10ms", "index.indexing.slowlog.threshold.index.info" : "50ms", "index.indexing.slowlog.threshold.index.warn" : "100ms", "index.search.slowlog.threshold.fetch.debug" : "100ms", "index.search.slowlog.threshold.fetch.info" : "200ms", "index.search.slowlog.threshold.fetch.warn" : "500ms", "index.search.slowlog.threshold.query.debug" : "100ms", "index.search.slowlog.threshold.query.info" : "200ms", "index.search.slowlog.threshold.query.warn" : "1s" } }
11、TCP 设置多个端口的用途
transport.tcp.port
这个参数不写,默认为9300-9399
,开放那么多 端口有用么?
- 如果设置一个端口,假设这个端口占用了程序就无法正常启动;
- 如果设置多个端口,一个端口占用会寻找下一个端口,直至找到可用端口。
12、ES 临时重启,设置分片延迟分配策略
PUT _all/_settings
{
"settings": {
"index.unassigned.node_left.delayed_timeout": "5m"
}
}
三、Kibana
1、kibana 图表自定义标注
可以用 TSVB,支持标注。
Kibana TSVB 注解的使用:https://elasticsearch.cn/article/701
2、Kibana discover 导出 csv 文件
请参考文章:如何快速把 Kibana Discover 页的 Document Table 导出成 CSV
3、修改 kibana 的默认主页
四、社区文章精选
Any Code,Code Any!
扫码关注『AnyCode』,编程路上,一起前行。
ELK 使用小技巧(第 4 期)
Elasticsearch • rochy 发表了文章 • 6 个评论 • 5156 次浏览 • 2019-01-07 20:43
ELK Tips 主要介绍一些 ELK 使用过程中的小技巧,内容主要来源为 Elastic 中文社区。
一、Logstash
1、Logstash 性能调优主要参数
pipeline.workers
:设置启动多少个线程执行 fliter 和 output;当 input 的内容出现堆积而 CPU 使用率还比较充足时,可以考虑增加该参数的大小;pipeline.batch.size
:设置单个工作线程在执行过滤器和输出之前收集的最大事件数,较大的批量大小通常更高效,但会增加内存开销。输出插件会将每个批处理作为一个输出单元。;例如,ES 输出会为收到的每个批次发出批量请求;调整pipeline.batch.size
可调整发送到 ES 的批量请求(Bulk)的大小;pipeline.batch.delay
:设置 Logstash 管道的延迟时间, 管道批处理延迟是 Logstash 在当前管道工作线程中接收事件后等待新消息的最长时间(以毫秒为单位);简单来说,当pipeline.batch.size
不满足时,会等待pipeline.batch.delay
设置的时间,超时后便开始执行 filter 和 output 操作。
2、使用 Ruby Filter 根据现有字段计算一个新字段
filter {
ruby {
code => "event.set('kpi', ((event.get('a') + event.get('b'))/(event.get('c')+event.get('d'))).round(2))"
}
}
3、logstash filter 如何判断字段是够为空或者 null
if ![updateTime]
4、Date Filter 设置多种日期格式
date {
match => ["logtime", "yyyy-MM-dd HH:mm:ss.SSS","yyyy-MM-dd HH:mm:ss,SSS"]
target => "logtime_utc"
}
二、Elasticsearch
1、高效翻页 Search After
通常情况下我们会使用 from 和 size 的方式实现查询结果的翻页,但是当达到深度分页时,成本变得过高(堆内存占用和时间耗费与 from+size 的大小成正比),因此 ES 设置了限制(index.max_result_window
),默认值为 10000,防止用户进行过于深入的翻页。
推荐使用 Scroll api 进行高效深度滚动,但滚动上下文代价很高,因此不要将 Scroll 用于实时用户请求。search_after 参数通过提供实时游标来解决深度滚动的问题,其主要思路是使用上一页的结果来帮助检索下一页。
GET twitter/_search
{
"size": 10,
"query": {
"match" : {
"title" : "elasticsearch"
}
},
"search_after": [1463538857, "654323"],
"sort": [
{"date": "asc"},
{"tie_breaker_id": "asc"}
]
}
2、ES 文档相似度 BM25 参数设置
ES2.X 默认是以 TF/IDF 算法计算文档相似度,从 ES5.X 开始,BM25 作为默认的相似度计算算法。
PUT /index
{
"settings" : {
"index" : {
"similarity" : {
"my_similarity" : {
"type" : "DFR",
"basic_model" : "g",
"after_effect" : "l",
"normalization" : "h2",
"normalization.h2.c" : "3.0"
}
}
}
}
}
PUT /index/_mapping/_doc
{
"properties" : {
"title" : { "type" : "text", "similarity" : "my_similarity" }
}
}
3、ES2.X 得分计算
得分计算脚本:
double tf = Math.sqrt(doc.freq);
double idf = Math.log((field.docCount+1.0)/(term.docFreq+1.0)) + 1.0;
double norm = 1/Math.sqrt(doc.length);
return query.boost * tf * idf * norm;
- 忽略词频统计及词频位置:将字段的
index_options
设置为docs
; - 忽略字段长度:设置字段的
"norms": { "enabled": false }
;
4、CircuitBreakingException: [parent] Data too large
报错信息:
[WARN ][r.suppressed ] path: /, params: {}
org.elasticsearch.common.breaker.CircuitBreakingException: [parent] Data too large, data for [<http_request>] would be [1454565650/1.3gb], which is larger than the limit of [1454427340/1.3gb], usages [request=0/0b, fielddata=568/568b, in_flight_requests=0/0b, accounting=1454565082/1.3gb]
jvm 堆内存不够当前查询加载数据所以会报 data too large, 请求被熔断,indices.breaker.request.limit
默认为 jvm heap 的 60%,因此可以通过调整 ES 的 Heap Size 来解决该问题。
5、ES 免费的自动化运维工具推荐
- Ansible: https://github.com/elastic/ansible-elasticsearch
- Puppet: https://github.com/elastic/puppet-elasticsearch
- Cookbook: https://github.com/elastic/cookbook-elasticsearch
- Curator:https://www.elastic.co/guide/en/elasticsearch/client/curator/current/about.html
6、elasticsearch-hanlp 分词插件包
核心功能:
- 内置多种分词模式,适合不同场景;
- 内置词典,无需额外配置即可使用;
- 支持外置词典,用户可自定义分词算法,基于词典或是模型;
- 支持分词器级别的自定义词典,便于用于多租户场景;
- 支持远程词典热更新(待开发);
- 拼音过滤器、繁简体过滤器(待开发);
- 基于词语或单字的 ngram 切分分词(待开发)。
7、节点重启时延迟索引分片重分配
当某个节点短时间离开集群时,一般是不会影响整体系统运行的,可以通过下面的请求延迟索引分片的再分配。
PUT _all/_settings
{
"settings": {
"index.unassigned.node_left.delayed_timeout": "5m"
}
}
8、ES 数据修改后,查询还是未修改前的数据
默认是 1 秒可见,如果你的需求一定要写完就可见,那在写的时候增加 refresh 参数,强制刷新即可,但强烈建议不这么干,因为这样会把整个集群拖垮。
9、Terms Query 从另一个索引获取 terms
当 Terms Query 需要指定很多 terms 的时候,如果手动设置还是相当麻烦的,可以通过 terms-lookup 的方式从另外一个索引加载需要匹配的 terms。
PUT /users/_doc/2
{
"followers" : ["1", "3"]
}
PUT /tweets/_doc/1
{
"user" : "1"
}
GET /tweets/_search
{
"query" : {
"terms" : {
"user" : {
"index" : "users",
"type" : "_doc",
"id" : "2",
"path" : "followers"
}
}
}
}
-----------等效下面的语句--------------
PUT /users/_doc/2
{
"followers" : [
{
"id" : "1"
},
{
"id" : "2"
}
]
}
10、ES 备份路径设置
报错信息:
doesn't match any of the locations specified by path.repo because this setting is empty
结局方案,修改 ES 的配置文件:
# 在 elasticsearch.yml 中添加下面配置来设置备份仓库路径
path.repo: ["/home/test/backup/zty_logstash"]
11、Query cache 和 Filter cache 的区别
Filter cache 被重命名为 Node Query Cache,也就是说 Query cache 等同于 Filter cache;Query Cache 采用了 LRU 的缓存方式(当缓存满的时候,淘汰旧的不用的缓存数据),Query Cache 只缓存被用于 filter 上下文的内容。
12、Shard 大小需要考虑的因素有哪些?
Lucene 底层没有这个大小的限制,20-40GB 的这个区间范围本身就比较大,经验值有时候就是拍脑袋,不一定都好使。
- Elasticsearch 对数据的隔离和迁移是以分片为单位进行的,分片太大,会加大迁移成本;
- 一个分片就是一个 Lucene 的库,一个 Lucene 目录里面包含很多 Segment,每个 Segment 有文档数的上限,Segment 内部的文档 ID 目前使用的是 Java 的整型,也就是 2 的 31 次方,所以能够表示的总的文档数为 Integer.MAX_VALUE - 128 = 2^31 - 128 = 2147483647 - 1 = 2,147,483,519,也就是21.4亿条;
- 同样,如果你不 force merge 成一个 Segment,单个 shard 的文档数能超过这个数;
- 单个 Lucene 越大,索引会越大,查询的操作成本自然要越高,IO 压力越大,自然会影响查询体验;
- 具体一个分片多少数据合适,还是需要结合实际的业务数据和实际的查询来进行测试以进行评估。
13、ES 索引更新时通过 mapping 限制指定字段更新
Elasticsearch 默认是 Dynamic Mapping,新字段会自动猜测数据类型,并自动 merge 到之前的 Mapping,你可以在 Mapping 里面可以配置字段是否支持动态加入,设置参数dynamic即可:true,默认,表示支持动态加入新字段;false,表示忽略该字段的后续索引等操作,但是索引还是成功的;strict支持不支持未知字段,直接抛错。
14、ES 数据快照到 HDFS
ES 做快照和使用 ES-Hadoop 导数据是完全的两种不同的方式,使用 ES-Hadoopp 后期导入的成本可能也不小。
- 如果要恢复快,当然是做快照和还原的方式最快,速度完全取决于网络和磁盘的速度;
- 如果为了节省磁盘,快照的时候,可以选 6.5 最新支持的
source_only
模式,导出的快照要小很多,不过恢复的时候要进行重建,速度慢。
15、segment.memory 简介
segment 的大小,和 indexing buffer 有关,有三种方式会生成 segment:
- 一种是 indexing buffer 写满了会生成 segment 文件,默认是堆内存的10%,是节点共享的;
- 一种是 index buffer 有文档,但是还没满,但是 refresh 时间到了,这个时候就会把 buffer 里面的生成 segment 文件;
- 还有最后一种就是 es 自动的会将小的 segment 文件定期合并产生新的 segment 文件。
三、社区文章精选
- 2018 年 Elastic Advent Calendar 分享活动
- 使用 ES-Hadoop 将 Spark Streaming 流数据写入 ES
- Elastic Stack 6.5 最新功能
- 让Elasticsearch飞起来!——性能优化实践干货
Any Code,Code Any!
扫码关注『AnyCode』,编程路上,一起前行。
Day 1 - ELK 使用小技巧(第 3 期)
Advent • rochy 发表了文章 • 1 个评论 • 4863 次浏览 • 2018-12-01 02:28
ELK Tips 主要介绍一些 ELK 使用过程中的小技巧,内容主要来源为 Elastic 中文社区。
一、Logstash
1、Filebeat 设置多个 output
在 6.0 之前,Filebeat 可以设置多个输出(必须是不同类型的输出);从 6.0 开始已经禁止多输出了,只能拥有一个输出,如果想实现多输出,可以借助 logstash 等中间组件进行输出分发。
二、Elasticsearch
1、ES 用户占用的内存大于为 ES 设置的 heapsize
ES 是 Java 应用,底层存储引擎是基于 Lucene 的,heapsize 设置的是 Java 应用的内存;而 Lucene 建立倒排索引(Inverted Index)是先在内存里生成,然后定期以段文件(segment file)的形式刷到磁盘的,因此 Lucene 也会占用一部分内存。
2、ES 使用别名插入数据
ES 可以通过索引的方式向索引插入数据,但是同时只能有一个索引可以被写入,而且需要手动设置,未设置的情况下会报错:no write index is defined for alias [xxxx], The write index may be explicitly disabled using is_write_index=false
or the alias points to multiple indices without one being designated as a write index。
POST /_aliases
{
"actions" : [
{
"add" : {
"index" : "test",
"alias" : "alias1",
"is_write_index" : true
}
}
]
}
3、ES 设置 G1 垃圾回收
修改 jvm.options
文件,将下面几行:
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly
改为
-XX:+UseG1GC
-XX:MaxGCPauseMillis=50
即可。
其中 -XX:MaxGCPauseMillis
是控制预期的最高 GC 时长,默认值为 200ms,如果线上业务特性对于 GC 停顿非常敏感,可以适当设置低一些。但是这个值如果设置过小,可能会带来比较高的 cpu 消耗。
4、ES 和 Zipkin 集成时设置验证信息
java -DKAFKA_ZOOKEEPER=10.14.123.117:2181
-DSTORAGE_TYPE=elasticsearch
-DES_HOSTS=http://10.14.125.5:9200
ES_USERNAME=xxx ES_PASSWORD=xxx
-jar zipkin.jar
5、ES 集群部署报错
问题 1 报错信息如下:
Received message from unsupported version:[2.0.0] minimal compatible version is:[5.6.0]
经排查是集群中存在低版本的 ES 实例,将低版本实例移除即可。
问题 2 报错信息如下:
with the same id but is a different node instance
删除对应节点 elsticsearch 文件夹下的 data 文件夹下的节点数据即可。
6、海量中文分词插件
海量分词是天津海量信息技术股份有限公司自主研发的中文分词核心,经测试分词效果还是不错的,值得一试。
7、查询一个索引下的所有 type 名
通过下面的 API,即可获取全部的 type,下面的例子中 doc 就是 indexName 索引下的一个 type:
GET http://es127.0.0.1:9200/indexName/_mappings
-----------------------------------------------
{
indexName: - {
mappings: - {
doc: - {
_all: + {... },
dynamic_date_formats: + [... ],
dynamic_templates: + [... ],
properties: + {... }
}
}
}
}
8、索引模板中根据字段值设置别名
设置索引模板的时候,别名可以使用 Query 条件来进行匹配。
PUT _template/template_1
{
"index_patterns" : ["te*"],
"settings" : {
"number_of_shards" : 1
},
"aliases" : {
"alias2" : {
"filter" : {
"term" : {"user" : "kimchy" }
},
"routing" : "kimchy"
},
"{index}-alias" : {}
}
}
9、索引模板设置默认时间匹配格式
ES 默认是不会将 yyyy-MM-dd HH:mm:ss 识别为时间的,可以通过在索引模板进行如下设置实现多种时间格式的识别:
"mappings": {
"doc": {
"dynamic_date_formats": ["yyyy-MM-dd HH:mm:ss||strict_date_optional_time||epoch_millis"],
10、ES 中 Merge 相关设置
Merge 是非常耗费 CPU 的操作;而且如果不是 SSD 的话,推荐将 index.merge.scheduler.max_thread_count 设置为 1;否则 ES 会启动 Math.min(3, Runtime.getRuntime().availableProcessors() / 2) 个线程进行 Merge 操作;这样大部分机械硬盘的磁盘 IO 都很难承受,就可能出现阻塞。
"index": {
"refresh_interval": "5s",
"number_of_shards": "3",
"max_result_window": 10000,
"translog": {
"flush_threshold_size": "500mb",
"sync_interval": "30s",
"durability": "async"
},
"merge": {
"scheduler": {
"max_merge_count": "100",
"max_thread_count": "1"
}
},
11、mapping 中 enabled store index 参数
- enabled:默认是true,只用于 mapping 中的 object 字段类型;当设置为 false 时,其作用是使 es 不去解析该字段,并且该字段不能被查询和 store,只有在 source 中才能看到,设置 enabled 为 false,可以不设置字段类型,默认类型为 object;
- store:默认 false,store 参数的功能和 source 有一些相似,我们的数据默认都会在 source 中存在,但我们也可以将数据 store 起来;当我们使用
copy_to
参数时,copy_to
的目标字段并不会在 source 中存储,此时 store 就派上用场了; - index:默认是 true,当设置为 false,表明该字段不能被查询,如果查询会报错。
12、ES 图片搜索
- 可以借助局部敏感 LSH 或者 pHash 来实现:https://stackoverflow.com/questions/32785803
- Github 也有一个开源项目使用了多种 Hash 算法借助 ES 来实现图片搜索:https://github.com/usc-isi-i2/elasticsearch-image-features
13、Term 聚合根据子聚合结果排序
GET /_search
{
"aggs" : {
"genres" : {
"terms" : {
"field" : "genre",
"order" : { "playback_stats.max" : "desc" }
},
"aggs" : {
"playback_stats" : { "stats" : { "field" : "play_count" } }
}
}
}
}
三、社区文章精选
ELK 使用小技巧(第 2 期)
Elasticsearch • rochy 发表了文章 • 1 个评论 • 7043 次浏览 • 2018-11-17 18:36
ELK Tips 主要介绍一些 ELK 使用过程中的小技巧,内容主要来源为 Elastic 中文社区。
一、Logstash
1、Filebeat :Non-zero metrics in the last 30s
- 问题表现:Filebeat 无法向 Elasticsearch 发送日志数据;
- 错误信息:
INFO [monitoring] 1og/log.go:124 Non-zero metrics in the last 30s
; - 社区反馈:在 input 和 output 下面添加属性 enabled:true。
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/*.log
output.elasticsearch:
hosts: ["https://localhost:9200"]
username: "filebeat_internal"
password: "YOUR_PASSWORD"
enabled: true
input 和 output 下 enabled 属性默认值为 true,因此怀疑另有其因。
2、Logstash 按月生成索引
output {
if [type] == "typeA"{
elasticsearch {
hosts => "127.0.0.1:9200"
index => "log_%{+YYYY_MM}"
}
}
}
按照日的原理类似:%{+YYYY.MM.dd}
3、Filebeat 通过配置删除特定字段
Filebeat 实现了类似 Logstash 中 filter 的功能,叫做处理器(processors),processors 种类不多,尽可能在保持 Filebeat 轻量化的基础上提供更多常用的功能。
下面列几种常用的 processors:
add_cloud_metadata
:添加云服务器的 meta 信息;add_locale
:添加本地时区;decode_json_fields
:解析并处理包含 Json 字符串的字段;drop_event
:丢弃符合条件的消息事件;drop_fields
:删除符合条件的字段;include_fields
:选择符合条件的字段;rename
:字段重命名;add_kubernetes_metadata
:添加 k8s 的 meta 信息;add_docker_metadata
:添加容器的 meta 信息;add_host_metadata
:添加操作系统的 meta 信息;dissect
:类似与 gork 的正则匹配字段的功能;dns
:配置 filebeat 独立的 dns 解析方式;add_process_metadata
:添加进程的元信息。
processors 的使用方式:
- type: <input_type>
processors:
- <processor_name>:
when:
<condition>
<parameters>
...
4、LogStash 采集 FTP 日志文件
exec {
codec => plain { }
command => "curl ftp://server/logs.log"
interval => 3000}
}
5、Logstash docker-compose 启动失败(Permission denied)
在 docker-compose 中使用 user 选项设置使用 root 用户启动 docker,能解决权限问题。
$ cat docker-compose.yml
version: '2'
services:
logstash:
image: docker.elastic.co/logstash/logstash:6.4.2
user: root
command: id
6、Metricize filter plugin
将一条消息拆分为多条消息。
# 原始信息
{
type => "type A"
metric1 => "value1"
metric2 => "value2"
}
# 配置信息
filter {
metricize {
metrics => [ "metric1", "metric2" ]
}
}
# 最终输出
{ {
type => "type A" type => "type A"
metric => "metric1" metric => "metric2"
value => "value1" value => "value2"
} }
二、Elasticsearch
1、ES 倒排索引内部结构
Lucene 的倒排索引都是按照字段(field)来存储对应的文档信息的,如果 docName 和 docContent 中有“苹果”这个 term,就会有这两个索引链,如下所示:
docName:
"苹果" -> "doc1, doc2, doc3..."
docContent:
"苹果" -> "doc2, doc4, doc6..."
2、Jest 和 RestHighLevelClient 哪个好用点
RestHighLevelClient 是官方组件,会一直得到官方的支持,且会与 ES 保持同步更新,推荐使用官方的高阶 API。
Jest 由于是社区维护,所以更新会有一定延迟,目前最新版对接 ES6.3.1,近一个月只有四个 issue,说明整体活跃度较低,因此不推荐使用。
此外推荐一份 TransportClient 的中文使用手册,翻译的很不错:https://github.com/jackiehff/elasticsearch-client-java-api-cn。
3、ES 单分片使用 From/Size 分页遇到重复数据
常规情况下 ES 单分片使用 From/Size 是不会遇到数据重复的,数据重复的可能原因有:
- 没有添加排序;
- 添加了按得分排序,但是查询语句全部为 filter 过滤条件(此时得分都一致);
- 添加了排序,但是有索引中文档的新增、修改、删除等操作。
对于多分片,推荐添加 preference 参数来实现分页结果的一致性。
4、The number of object passed must be even but was [1]
ES 在调用 setSource 的时候传入 Json 对象后会报错:The number of object passed must be even but was [1],此时可以推荐将 Json 对象转为 Map 集合,或者把 Json 对象转为 json 字符串,不过传入字符串的时候需要设置类型。
IndexRequest indexRequest = new IndexRequest("index", "type", "id");
JSONObject doc = new JSONObject();
//indexRequest.source(jsonObject); 错误的使用方法
//转为 Map 对象
indexRequest.source(JSONObject.parseObject((String) doc.get("json"), Map.class));
//转为 Json 字符串(声明字符串类型)
indexRequest.source(JSON.toJSONString(doc), XContentType.JSON);
5、跨集群搜索
ES 6.X 原生支持跨集群搜索,具体配置请参考:https://www.elastic.co/guide/en/kibana/current/management-cross-cluster-search.html
PUT _cluster/settings
{
"persistent": {
"cluster": {
"remote": {
"cluster_one": {
"seeds": [
"127.0.0.1:9300"
]
},
"cluster_two": {
"seeds": [
"127.0.0.1:9301"
]
},
"cluster_three": {
"seeds": [
"127.0.0.1:9302"
]
}
}
}
}
}
ES 6.5 推出了新功能,跨集群同步(Cross-cluster replication),感兴趣的可以自行了解。
6、ES 排序时设置空值排序位置
GET /_search
{
"sort" : [
{ "price" : {"missing" : "_last"} }
],
"query" : {
"term" : { "product" : "chocolate" }
}
}
7、ES 冷归档数据如何处理
使用相对低配的大磁盘机器配置为 ES 的 Warm Nodes,可以通过 index.routing.allocation.require.box_type
来设置索引是冷数据或者热数据。如果索引极少使用,可以 close 索引,然后在需要搜索的时候 open 即可。
8、ES 相似文章检测
对于大文本的去重,可以参考 SimHash 算法,通过 SimHash 可以提取到文档指纹(64位),两篇文章通过 SimHash 计算海明距离即可判断是否重复。海明距离计算,可以通过插件实现:https://github.com/joway/elasticsearch-hamming-plugin
9、Terms 聚合查询优化
- 如果只需要聚合后前 N 条记录,推荐在 Terms 聚合时添加上
"collect_mode": "breadth_first"
; - 此外可以通过设置
"min_doc_count": 10
来限制最小匹配文档数; - 如果对返回的 Term 有所要求,可以通过设置
include
和exclude
来过滤 Term; - 如果想获取全部 Term 聚合结果,但是聚合结果又很多,可以考虑将聚合分成多个批次分别取回(Filtering Values with partitions)。
10、Tomcat 字符集造成的 ES 查询无结果
两个系统连接同一个 ES 服务,配置和代码完全一致,同一个搜索条件,一个能够搜索出来东西,一个什么都搜索不出来,排查结果是因为其中一个系统的 tomcat 配置有问题,导致请求的时候乱码了,所以搜不到数据。
11、ES 索引设置默认分词器
默认情况下,如果字段不指定分词器,ES 或使用 standard 分词器进行分词;可以通过下面的设置更改默认的分词器。
2.X 支持设置默认的索引分词器(default_index)和默认的查询分词器(default_search),6.X 已经不再支持。
PUT /index
{
"settings": {
"analysis": {
"analyzer": {
"default": {
"type": "ik_max_word",
"tokenizer": "ik_max_word"
}
}
}
}
}
12、ES 中的魔法参数
- 索引名:_index
- 类型名:_type
- 文档Id:_id
- 得分:_score
- 索引排序:_doc
如果你对排序没有特别的需求,推荐使用 _doc 进行排序,例如执行 Scroll 操作时。
13、ES 延迟执行数据上卷(Rollup )
Rollup job 有个 delay 参数控制 job 执行的延迟时间,默认情况下不延迟执行,这样如果某个 interval 的数据已经聚合好了,该 interval 迟到的数据是不会处理的。
好在 rollup api 可以支持同时搜索裸索引和 rollup 过的索引,所以如果数据经常有延迟的话,可以考虑设置一个合适的 delay,比如 1h、6h 甚至 24h,这样 rollup 的索引产生会有延迟,但是能确保迟到的数据被处理。
从应用场景上看,rollup 一般是为了对历史数据做聚合存放,减少存储空间,所以延迟几个小时,甚至几天都是合理的。搜索的时候,同时搜索最近的裸索引和历史的 rollup 索引,就能将两者的数据组合起来,在给出正确的聚合结果的情况下,又兼顾了性能。
Rollup 是实验性功能,不过非常有用,特别是使用 ES 做数据仓库的场景。
14、ES6.x 获取所有的聚合结果
ES2.x 版本中,在聚合查询时,通过设置 setSize(0)
就可以获取所有的聚合结果,在ES6.x 中直接设置 setSize(Integer.MAX_VALUE)
等效于 2.x 中设置为 0。
15、ES Jar 包冲突问题
经常会遇到 ES 与业务集成时出现 Jar 包冲突问题,推荐的解决方法是使用 maven-shade-plugin
插件,该插件通过将冲突的 Jar 包更换一个命名空间的方式来解决 Jar 包的冲突问题,具体使用可以参考文章:https://www.jianshu.com/p/d9fb7afa634d。
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>com.google.guava</pattern>
<shadedPattern>net.luculent.elasticsearch.guava</shadedPattern>
</relocation>
<relocation>
<pattern>com.fasterxml.jackson</pattern>
<shadedPattern>net.luculent.elasticsearch.jackson</shadedPattern>
</relocation>
<relocation>
<pattern>org.joda</pattern>
<shadedPattern>net.luculent.elasticsearch.joda</shadedPattern>
</relocation>
<relocation>
<pattern>com.google.common</pattern>
<shadedPattern>net.luculent.elasticsearch.common</shadedPattern>
</relocation>
<relocation>
<pattern>com.google.thirdparty</pattern>
<shadedPattern>net.luculent.elasticsearch.thirdparty</shadedPattern>
</relocation>
</relocations>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer" />
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
16、ES 如何选择 Shard 存储文档?
ES 采用 djb2 哈希算法对要索引文档的指定(或者默认随机生成的)_id
进行哈希,得到哈希结果后对索引 shard 数目 n 取模,公式如下:hash(_id) % n
;根据取模结果决定存储到哪一个 shard 。
三、Kibana
1、在 Kiabana 的 Discovery 界面显示自定义字段
Kibana 的 Discovery 界面默认只显示 time 和 _source 两个字段,这个界面的左半部分,在 Popular 下面展示了很多,你只需要在你需要展示的字段后面点击 add 即可将自定义的字段添加到 discovery 界面。
2、filebeat 的 monitor 指标的说明
- Total:'All events newly created in the publishing pipeline'
- Emitted: 'Events processed by the output (including retries)'
- Acknowledged:'Events acknowledged by the output (includes events dropped by the output)'
- Queued:'Events added to the event pipeline queue'
四、社区文章精选
- Elastic认证考试心得
- 一文快速上手Logstash
- 当Elasticsearch遇见Kafka--Kafka Connect
- elasticsearch冷热数据读写分离
- elasticsearch优秀实践
- ELK 使用小技巧(第 1 期)
Any Code,Code Any!
扫码关注『AnyCode』,编程路上,一起前行。
kibana如何在图标上默认显示数据
Kibana • juneryang 回复了问题 • 4 人关注 • 2 个回复 • 4427 次浏览 • 2017-12-01 18:14
Elasticsearch 安全加固 101
Elasticsearch • medcl 发表了文章 • 8 个评论 • 21746 次浏览 • 2017-01-13 13:03
- 9200的 HTTP 接口之上加上 Nginx 来提供 Http Basic-Auth 的基本的身份认证,辅助 SSL 证书进行传输层的加密,Nginx 进一步限制可接受 Verb 请求类型及可被操作的索引前缀。
- 使用 Elastic 的 X-Pack 插件,同样提供了 Http Basic-Auth 和 SSL 传输层的加密,X-Pack 还能提供内外 Elasticsearch 集群节点间的流量加密,避免旁路攻击。
sudo -u es-user ES_JAVA_OPTS="-Xms1024m -Xmx1024m" /opt/elasticsearch/bin/elasticsearc
正确设置 Elasticsearch 的数据目录
请确保 Elasticsearch 的目录分配了合理的读写权限,避免使用共享文件系统,确保只有 elasticsearch 的启动用户才能访问,同理,日志目录也一样需要正确配置,避免泄露敏感信息。
文档君:https://www.elastic.co/guide/e ... tings
定期对 Elasticsearch 进行备份
使用 Elasticsearch 提供的备份还原机制,定期对 Elasticsearch 的数据进行快照备份,以备不时之需。
文档君:https://www.elastic.co/guide/e ... .html
加上监控和预警
Elasticsearch 提供了很好的默认参数,对参数方面还做了正确性检测,bootstrap 启动检查,不准确的参数,直接不允许 Elasticsearch 启动,以至于有很多人抱怨,怎么现在部署到线上默认就需要做这么多设置才能使用呢,是的,以前启动就默认绑定了所有的网卡,集群见自动发现和相连,现在需要手动绑定局域网网卡,默认只是绑定的本机127.0.0.1的 ip,对上线来说麻烦了一点,做了这些检查也就是为了保证数据安全,以前很多的公网都能直接访问的 Elasticsearch 实例,都是因为默认设置就绑定了公网 ip,但是这些还不够,作为用户,你还需要收集各种日志和系统监控信息,及时主动掌握服务健康和资源使用情况,发现异常情况要及时处理,这里提供一些方案:
- 使用开源的 Elastic Stack 收集这些日志,可以使用 Filebeat 收集日志,Metricbeat收集系统监控信息,存进 Elasticsearch,一旦发现异常的波动,使用 Watcher 来进行预警,通过邮件或者 webhook 调用短信、微信或者电话。
- 使用其他厂商的安全监控产品。
- 使用托管的 Elasticsearch 云的产品,如 Elastic Cloud等等。
Elasticsearch 安全加固 101
Elasticsearch • medcl 发表了文章 • 8 个评论 • 21746 次浏览 • 2017-01-13 13:03
- 9200的 HTTP 接口之上加上 Nginx 来提供 Http Basic-Auth 的基本的身份认证,辅助 SSL 证书进行传输层的加密,Nginx 进一步限制可接受 Verb 请求类型及可被操作的索引前缀。
- 使用 Elastic 的 X-Pack 插件,同样提供了 Http Basic-Auth 和 SSL 传输层的加密,X-Pack 还能提供内外 Elasticsearch 集群节点间的流量加密,避免旁路攻击。
sudo -u es-user ES_JAVA_OPTS="-Xms1024m -Xmx1024m" /opt/elasticsearch/bin/elasticsearc
正确设置 Elasticsearch 的数据目录
请确保 Elasticsearch 的目录分配了合理的读写权限,避免使用共享文件系统,确保只有 elasticsearch 的启动用户才能访问,同理,日志目录也一样需要正确配置,避免泄露敏感信息。
文档君:https://www.elastic.co/guide/e ... tings
定期对 Elasticsearch 进行备份
使用 Elasticsearch 提供的备份还原机制,定期对 Elasticsearch 的数据进行快照备份,以备不时之需。
文档君:https://www.elastic.co/guide/e ... .html
加上监控和预警
Elasticsearch 提供了很好的默认参数,对参数方面还做了正确性检测,bootstrap 启动检查,不准确的参数,直接不允许 Elasticsearch 启动,以至于有很多人抱怨,怎么现在部署到线上默认就需要做这么多设置才能使用呢,是的,以前启动就默认绑定了所有的网卡,集群见自动发现和相连,现在需要手动绑定局域网网卡,默认只是绑定的本机127.0.0.1的 ip,对上线来说麻烦了一点,做了这些检查也就是为了保证数据安全,以前很多的公网都能直接访问的 Elasticsearch 实例,都是因为默认设置就绑定了公网 ip,但是这些还不够,作为用户,你还需要收集各种日志和系统监控信息,及时主动掌握服务健康和资源使用情况,发现异常情况要及时处理,这里提供一些方案:
- 使用开源的 Elastic Stack 收集这些日志,可以使用 Filebeat 收集日志,Metricbeat收集系统监控信息,存进 Elasticsearch,一旦发现异常的波动,使用 Watcher 来进行预警,通过邮件或者 webhook 调用短信、微信或者电话。
- 使用其他厂商的安全监控产品。
- 使用托管的 Elasticsearch 云的产品,如 Elastic Cloud等等。
ELK 使用小技巧(第 5 期)
Elasticsearch • rochy 发表了文章 • 0 个评论 • 6030 次浏览 • 2019-02-22 12:24
ELK Tips 主要介绍一些 ELK 使用过程中的小技巧,内容主要来源为 Elastic 中文社区。
一、Logstash
1、Logstash 性能调优主要参数
pipeline.workers
:设置启动多少个线程执行 fliter 和 output;当 input 的内容出现堆积而 CPU 使用率还比较充足时,可以考虑增加该参数的大小;pipeline.batch.size
:设置单个工作线程在执行过滤器和输出之前收集的最大事件数,较大的批量大小通常更高效,但会增加内存开销。输出插件会将每个批处理作为一个输出单元。;例如,ES 输出会为收到的每个批次发出批量请求;调整pipeline.batch.size
可调整发送到 ES 的批量请求(Bulk)的大小;pipeline.batch.delay
:设置 Logstash 管道的延迟时间, 管道批处理延迟是 Logstash 在当前管道工作线程中接收事件后等待新消息的最长时间(以毫秒为单位);简单来说,当pipeline.batch.size
不满足时,会等待pipeline.batch.delay
设置的时间,超时后便开始执行 filter 和 output 操作。
2、'reader' unacceptable character ' ' (0x0)
logstash 执行使用 Jdbc input plugin
后报错:
[main]-pipeline-manager] ERROR logstash.agent - Pipeline aborted due to error {
:exception=>#<Psych::SyntaxError: (): 'reader' unacceptable character ' ' (0x0) special characters are not allowed in "'reader'",
position 0 at line 0 column 0>, :backtrace=>["org/jruby/ext/psych/PsychParser.java:232:in parse'"
解决方案:删除 $USER_HOME/.logstash_jdbc_last_run
文件即可。
二、Elasticsearch
1、TermsQuery 与多个 TermQuery 的区别
当 terms 的个数较少的时候,TermsQuery 等效为 ConstantScoreQuery 内部包含多个 TermQuery:
Query q1 = new TermInSetQuery(new Term("field", "foo"), new Term("field", "bar"));
// 等效为下面的语句
BooleanQuery bq = new BooleanQuery();
bq.add(new TermQuery(new Term("field", "foo")), Occur.SHOULD);
bq.add(new TermQuery(new Term("field", "bar")), Occur.SHOULD);
Query q2 = new ConstantScoreQuery(bq);
当 terms 较多的时候,它将使用匹配的文档组合成一个位集,并在该位集上进行评分;此时查询效率比普通的 Bool 合并要更加高效。
当 terms 的个数较多时,TermsQuery 比多个 TermQuery 组合的查询效率更高。
2、ES 借助 nginx 配置域名
upstream /data/ {
server 192.168.187.xxx:9200;
keepalive 300 ;
}
server {
listen 80;
server_name testelk.xx.com;
keepalive_timeout 120s 120s;
location /data {
proxy_pass http://data/;
proxy_http_version 1.1;
proxy_set_header Connection "Keep-Alive";
proxy_set_header Proxy-Connection "Keep-Alive";
proxy_set_header X-Real-IP $remote_addr;
proxy_pass_header remote_user
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header X-Nginx-Proxy true;
}
}
3、ES Reindex 时如何不停止写入服务
方案一:kennywu76
ES 的 reindex 在索引有实时的 update/delete 的情况下,即使借助 alias,也没有办法实现真正的 zero down time。
增加新文档比较好办,通过 alias 切换写入到新索引,同时 reindex 做旧->新索引的数据传输即可;但是 update/delete 操作针对的文档如果还未从旧索引传输过来,直接对新索引操作会导致两个索引数据不一致。
我能够想到的(一个未经实际验证)的方案,前提是数据库里的文档有一个类似 last_update_time
字段记录文档最后更新的时间,用作写入 ES 文档的版本号,然后数据写入新索引的时候,url 里带上下面这样的参数:version_type=external_gt&version=xxxxxx
。
其中 version_type=external_gt
表示写入文档的版本号大于已有的文档版本号,或者文档不存在,写入才会成功,否则会抛版本冲突的异常。另外 delete 操作都要转换成 index 操作,index 的内容可以是一个空文档。
这样实时数据写入新索引和 reindex 可以同时进行,实时写入的数据应该具有更高的版本,总是能够成功,reindex 如果遇到版本冲突,说明该文档被实时部分更新过了,已经过时,可以直接放弃跳过。
该方案的缺陷:
- 要求数据源里的数据具有版本信息,可能因为各种局限,不太容易更改;
- delete 操作必须转化为写入一个空文档,delete 实际上是一个标记文档,并且本身也有版本信息。但是如果后端发生了 segment merge,delete 可能会被合并以后物理清除。这样 delete 和对应的版本信息丢失,之后 reindex 如果写入了旧版本的文档,仍然会有一致性问题;但是空文档会增加索引文件的大小,有额外的消耗,一个可能的缓解办法是在 reindex 全部做完以后,再做一次空文档的删除。
改进方案:the_best
重建索引步骤如下:
- 保证 delete 操作都要转换成 index 操作,index 的内容可以是一个空文档;
- 对老索引
old_index
(业务上的别名还是挂在老索引上)进行重索引操作(version_type=external
);curl -X POST 'http://<hostname>:9200/_reindex' { "conflicts": "proceed", "source": { "index": "old_index", "size": 1000 }, "dest": { "index": "new_index", "version_type": "external" } }
- 将别名切到 newIndex;
- 将重索引时间段内
old_index
产生的热数据,再捞一次到new_index
中(conflicts=proceed&version_type=external
);curl -X POST /_reindex { "conflicts": "proceed", "source": { "index": "old_index" "query": { "constant_score" : { "filter" : { "range" : { "data_update_time" : { "gte" : <reindex开始时刻前的毫秒时间戳> } } } } } }, "dest": { "index": "new_index", "version_type": "external" } }
- 手动做一次空文档的删除。
这种方式取决于重索引期间产生的数据量大小(会影响步骤4的用时),不过我们可以视具体业务情况灵活操作。比如说数据量比较大重索引我们用了10个小时(这10个小时内新产生了200多万的数据),在切别名前,我们可以按步骤(4)的调用方式,把近10个小时的数据再捞一遍到新索引中,如此迭代个几次,直到别名切完后,我们能保证最后一次的步骤(4)可以在较短时间内完成。
4、ES 节点通讯配置
http.port: 9200
http.bind_host: 127.0.0.1
transport.tcp.port: 9300
transport.bind_host: 127.0.0.1
5、把 Lucene 的原生 query 传给 ES
SearchRequest searchRequest = new SearchRequest(indexName);
searchRequest.types(typeName);
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.from(0);
sourceBuilder.size(10);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//q为Lucene检索表达式, 直接输入关键词匹配_all或者*字段, 字段匹配user:kimchy,
//多字段匹配user:kimchy AND message:Elasticsearch
QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(q);
sourceBuilder.query(queryStringQueryBuilder);
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest);
SearchHits searchHits = searchResponse.getHits();
6、ES 文档字段个数限制
ES 文档默认不允许文档字段超过 1000,超过 1000 会报如下错误:
failed to put mappings on indices [[[nfvoemspm/srjL3cMMRUqa7DgOrYqX-A]]], type [log]
java.lang.IllegalArgumentException: Limit of total fields [1000] in index [xxx] has been exceeded
可以通过修改索引配置来修改字段个数限制,不过还是推荐从业务上进行优化:
修改settings
{
"index.mapping.total_fields.limit": 2000
}
7、将 DSL 字符串转换为 QueryBuilder
## wrapper 案例
GET /_search
{
"query" : {
"wrapper": {
"query" : "eyJ0ZXJtIiA6IHsgInVzZXIiIDogIktpbWNoeSIgfX0="
}
}
}
## RestClient
QueryBuilders.wrapperQuery("{\"term\": {\"field\":\"value\"}}")
8、ES 集群重启后 Slice Scroll 速度变慢
重启机器之后,pagecache 都没有了,所有数据都要重新从磁盘加载。
9、ES 开启索引新建删除日志
PUT _cluster/settings
{
"persistent": {
"logger.cluster.service": "DEBUG"
}
}
10、慢日志全局级别设定
- 对已经存在的索引可以通过 PUT _settings 做存量设置
- 对之后新增的索引,可以使用类似于下面的template
PUT _template/global-slowlog_template { "order": -1, "version": 0, "template": "*", "settings": { "index.indexing.slowlog.threshold.index.debug" : "10ms", "index.indexing.slowlog.threshold.index.info" : "50ms", "index.indexing.slowlog.threshold.index.warn" : "100ms", "index.search.slowlog.threshold.fetch.debug" : "100ms", "index.search.slowlog.threshold.fetch.info" : "200ms", "index.search.slowlog.threshold.fetch.warn" : "500ms", "index.search.slowlog.threshold.query.debug" : "100ms", "index.search.slowlog.threshold.query.info" : "200ms", "index.search.slowlog.threshold.query.warn" : "1s" } }
11、TCP 设置多个端口的用途
transport.tcp.port
这个参数不写,默认为9300-9399
,开放那么多 端口有用么?
- 如果设置一个端口,假设这个端口占用了程序就无法正常启动;
- 如果设置多个端口,一个端口占用会寻找下一个端口,直至找到可用端口。
12、ES 临时重启,设置分片延迟分配策略
PUT _all/_settings
{
"settings": {
"index.unassigned.node_left.delayed_timeout": "5m"
}
}
三、Kibana
1、kibana 图表自定义标注
可以用 TSVB,支持标注。
Kibana TSVB 注解的使用:https://elasticsearch.cn/article/701
2、Kibana discover 导出 csv 文件
请参考文章:如何快速把 Kibana Discover 页的 Document Table 导出成 CSV
3、修改 kibana 的默认主页
四、社区文章精选
Any Code,Code Any!
扫码关注『AnyCode』,编程路上,一起前行。
ELK 使用小技巧(第 4 期)
Elasticsearch • rochy 发表了文章 • 6 个评论 • 5156 次浏览 • 2019-01-07 20:43
ELK Tips 主要介绍一些 ELK 使用过程中的小技巧,内容主要来源为 Elastic 中文社区。
一、Logstash
1、Logstash 性能调优主要参数
pipeline.workers
:设置启动多少个线程执行 fliter 和 output;当 input 的内容出现堆积而 CPU 使用率还比较充足时,可以考虑增加该参数的大小;pipeline.batch.size
:设置单个工作线程在执行过滤器和输出之前收集的最大事件数,较大的批量大小通常更高效,但会增加内存开销。输出插件会将每个批处理作为一个输出单元。;例如,ES 输出会为收到的每个批次发出批量请求;调整pipeline.batch.size
可调整发送到 ES 的批量请求(Bulk)的大小;pipeline.batch.delay
:设置 Logstash 管道的延迟时间, 管道批处理延迟是 Logstash 在当前管道工作线程中接收事件后等待新消息的最长时间(以毫秒为单位);简单来说,当pipeline.batch.size
不满足时,会等待pipeline.batch.delay
设置的时间,超时后便开始执行 filter 和 output 操作。
2、使用 Ruby Filter 根据现有字段计算一个新字段
filter {
ruby {
code => "event.set('kpi', ((event.get('a') + event.get('b'))/(event.get('c')+event.get('d'))).round(2))"
}
}
3、logstash filter 如何判断字段是够为空或者 null
if ![updateTime]
4、Date Filter 设置多种日期格式
date {
match => ["logtime", "yyyy-MM-dd HH:mm:ss.SSS","yyyy-MM-dd HH:mm:ss,SSS"]
target => "logtime_utc"
}
二、Elasticsearch
1、高效翻页 Search After
通常情况下我们会使用 from 和 size 的方式实现查询结果的翻页,但是当达到深度分页时,成本变得过高(堆内存占用和时间耗费与 from+size 的大小成正比),因此 ES 设置了限制(index.max_result_window
),默认值为 10000,防止用户进行过于深入的翻页。
推荐使用 Scroll api 进行高效深度滚动,但滚动上下文代价很高,因此不要将 Scroll 用于实时用户请求。search_after 参数通过提供实时游标来解决深度滚动的问题,其主要思路是使用上一页的结果来帮助检索下一页。
GET twitter/_search
{
"size": 10,
"query": {
"match" : {
"title" : "elasticsearch"
}
},
"search_after": [1463538857, "654323"],
"sort": [
{"date": "asc"},
{"tie_breaker_id": "asc"}
]
}
2、ES 文档相似度 BM25 参数设置
ES2.X 默认是以 TF/IDF 算法计算文档相似度,从 ES5.X 开始,BM25 作为默认的相似度计算算法。
PUT /index
{
"settings" : {
"index" : {
"similarity" : {
"my_similarity" : {
"type" : "DFR",
"basic_model" : "g",
"after_effect" : "l",
"normalization" : "h2",
"normalization.h2.c" : "3.0"
}
}
}
}
}
PUT /index/_mapping/_doc
{
"properties" : {
"title" : { "type" : "text", "similarity" : "my_similarity" }
}
}
3、ES2.X 得分计算
得分计算脚本:
double tf = Math.sqrt(doc.freq);
double idf = Math.log((field.docCount+1.0)/(term.docFreq+1.0)) + 1.0;
double norm = 1/Math.sqrt(doc.length);
return query.boost * tf * idf * norm;
- 忽略词频统计及词频位置:将字段的
index_options
设置为docs
; - 忽略字段长度:设置字段的
"norms": { "enabled": false }
;
4、CircuitBreakingException: [parent] Data too large
报错信息:
[WARN ][r.suppressed ] path: /, params: {}
org.elasticsearch.common.breaker.CircuitBreakingException: [parent] Data too large, data for [<http_request>] would be [1454565650/1.3gb], which is larger than the limit of [1454427340/1.3gb], usages [request=0/0b, fielddata=568/568b, in_flight_requests=0/0b, accounting=1454565082/1.3gb]
jvm 堆内存不够当前查询加载数据所以会报 data too large, 请求被熔断,indices.breaker.request.limit
默认为 jvm heap 的 60%,因此可以通过调整 ES 的 Heap Size 来解决该问题。
5、ES 免费的自动化运维工具推荐
- Ansible: https://github.com/elastic/ansible-elasticsearch
- Puppet: https://github.com/elastic/puppet-elasticsearch
- Cookbook: https://github.com/elastic/cookbook-elasticsearch
- Curator:https://www.elastic.co/guide/en/elasticsearch/client/curator/current/about.html
6、elasticsearch-hanlp 分词插件包
核心功能:
- 内置多种分词模式,适合不同场景;
- 内置词典,无需额外配置即可使用;
- 支持外置词典,用户可自定义分词算法,基于词典或是模型;
- 支持分词器级别的自定义词典,便于用于多租户场景;
- 支持远程词典热更新(待开发);
- 拼音过滤器、繁简体过滤器(待开发);
- 基于词语或单字的 ngram 切分分词(待开发)。
7、节点重启时延迟索引分片重分配
当某个节点短时间离开集群时,一般是不会影响整体系统运行的,可以通过下面的请求延迟索引分片的再分配。
PUT _all/_settings
{
"settings": {
"index.unassigned.node_left.delayed_timeout": "5m"
}
}
8、ES 数据修改后,查询还是未修改前的数据
默认是 1 秒可见,如果你的需求一定要写完就可见,那在写的时候增加 refresh 参数,强制刷新即可,但强烈建议不这么干,因为这样会把整个集群拖垮。
9、Terms Query 从另一个索引获取 terms
当 Terms Query 需要指定很多 terms 的时候,如果手动设置还是相当麻烦的,可以通过 terms-lookup 的方式从另外一个索引加载需要匹配的 terms。
PUT /users/_doc/2
{
"followers" : ["1", "3"]
}
PUT /tweets/_doc/1
{
"user" : "1"
}
GET /tweets/_search
{
"query" : {
"terms" : {
"user" : {
"index" : "users",
"type" : "_doc",
"id" : "2",
"path" : "followers"
}
}
}
}
-----------等效下面的语句--------------
PUT /users/_doc/2
{
"followers" : [
{
"id" : "1"
},
{
"id" : "2"
}
]
}
10、ES 备份路径设置
报错信息:
doesn't match any of the locations specified by path.repo because this setting is empty
结局方案,修改 ES 的配置文件:
# 在 elasticsearch.yml 中添加下面配置来设置备份仓库路径
path.repo: ["/home/test/backup/zty_logstash"]
11、Query cache 和 Filter cache 的区别
Filter cache 被重命名为 Node Query Cache,也就是说 Query cache 等同于 Filter cache;Query Cache 采用了 LRU 的缓存方式(当缓存满的时候,淘汰旧的不用的缓存数据),Query Cache 只缓存被用于 filter 上下文的内容。
12、Shard 大小需要考虑的因素有哪些?
Lucene 底层没有这个大小的限制,20-40GB 的这个区间范围本身就比较大,经验值有时候就是拍脑袋,不一定都好使。
- Elasticsearch 对数据的隔离和迁移是以分片为单位进行的,分片太大,会加大迁移成本;
- 一个分片就是一个 Lucene 的库,一个 Lucene 目录里面包含很多 Segment,每个 Segment 有文档数的上限,Segment 内部的文档 ID 目前使用的是 Java 的整型,也就是 2 的 31 次方,所以能够表示的总的文档数为 Integer.MAX_VALUE - 128 = 2^31 - 128 = 2147483647 - 1 = 2,147,483,519,也就是21.4亿条;
- 同样,如果你不 force merge 成一个 Segment,单个 shard 的文档数能超过这个数;
- 单个 Lucene 越大,索引会越大,查询的操作成本自然要越高,IO 压力越大,自然会影响查询体验;
- 具体一个分片多少数据合适,还是需要结合实际的业务数据和实际的查询来进行测试以进行评估。
13、ES 索引更新时通过 mapping 限制指定字段更新
Elasticsearch 默认是 Dynamic Mapping,新字段会自动猜测数据类型,并自动 merge 到之前的 Mapping,你可以在 Mapping 里面可以配置字段是否支持动态加入,设置参数dynamic即可:true,默认,表示支持动态加入新字段;false,表示忽略该字段的后续索引等操作,但是索引还是成功的;strict支持不支持未知字段,直接抛错。
14、ES 数据快照到 HDFS
ES 做快照和使用 ES-Hadoop 导数据是完全的两种不同的方式,使用 ES-Hadoopp 后期导入的成本可能也不小。
- 如果要恢复快,当然是做快照和还原的方式最快,速度完全取决于网络和磁盘的速度;
- 如果为了节省磁盘,快照的时候,可以选 6.5 最新支持的
source_only
模式,导出的快照要小很多,不过恢复的时候要进行重建,速度慢。
15、segment.memory 简介
segment 的大小,和 indexing buffer 有关,有三种方式会生成 segment:
- 一种是 indexing buffer 写满了会生成 segment 文件,默认是堆内存的10%,是节点共享的;
- 一种是 index buffer 有文档,但是还没满,但是 refresh 时间到了,这个时候就会把 buffer 里面的生成 segment 文件;
- 还有最后一种就是 es 自动的会将小的 segment 文件定期合并产生新的 segment 文件。
三、社区文章精选
- 2018 年 Elastic Advent Calendar 分享活动
- 使用 ES-Hadoop 将 Spark Streaming 流数据写入 ES
- Elastic Stack 6.5 最新功能
- 让Elasticsearch飞起来!——性能优化实践干货
Any Code,Code Any!
扫码关注『AnyCode』,编程路上,一起前行。
Day 1 - ELK 使用小技巧(第 3 期)
Advent • rochy 发表了文章 • 1 个评论 • 4863 次浏览 • 2018-12-01 02:28
ELK Tips 主要介绍一些 ELK 使用过程中的小技巧,内容主要来源为 Elastic 中文社区。
一、Logstash
1、Filebeat 设置多个 output
在 6.0 之前,Filebeat 可以设置多个输出(必须是不同类型的输出);从 6.0 开始已经禁止多输出了,只能拥有一个输出,如果想实现多输出,可以借助 logstash 等中间组件进行输出分发。
二、Elasticsearch
1、ES 用户占用的内存大于为 ES 设置的 heapsize
ES 是 Java 应用,底层存储引擎是基于 Lucene 的,heapsize 设置的是 Java 应用的内存;而 Lucene 建立倒排索引(Inverted Index)是先在内存里生成,然后定期以段文件(segment file)的形式刷到磁盘的,因此 Lucene 也会占用一部分内存。
2、ES 使用别名插入数据
ES 可以通过索引的方式向索引插入数据,但是同时只能有一个索引可以被写入,而且需要手动设置,未设置的情况下会报错:no write index is defined for alias [xxxx], The write index may be explicitly disabled using is_write_index=false
or the alias points to multiple indices without one being designated as a write index。
POST /_aliases
{
"actions" : [
{
"add" : {
"index" : "test",
"alias" : "alias1",
"is_write_index" : true
}
}
]
}
3、ES 设置 G1 垃圾回收
修改 jvm.options
文件,将下面几行:
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly
改为
-XX:+UseG1GC
-XX:MaxGCPauseMillis=50
即可。
其中 -XX:MaxGCPauseMillis
是控制预期的最高 GC 时长,默认值为 200ms,如果线上业务特性对于 GC 停顿非常敏感,可以适当设置低一些。但是这个值如果设置过小,可能会带来比较高的 cpu 消耗。
4、ES 和 Zipkin 集成时设置验证信息
java -DKAFKA_ZOOKEEPER=10.14.123.117:2181
-DSTORAGE_TYPE=elasticsearch
-DES_HOSTS=http://10.14.125.5:9200
ES_USERNAME=xxx ES_PASSWORD=xxx
-jar zipkin.jar
5、ES 集群部署报错
问题 1 报错信息如下:
Received message from unsupported version:[2.0.0] minimal compatible version is:[5.6.0]
经排查是集群中存在低版本的 ES 实例,将低版本实例移除即可。
问题 2 报错信息如下:
with the same id but is a different node instance
删除对应节点 elsticsearch 文件夹下的 data 文件夹下的节点数据即可。
6、海量中文分词插件
海量分词是天津海量信息技术股份有限公司自主研发的中文分词核心,经测试分词效果还是不错的,值得一试。
7、查询一个索引下的所有 type 名
通过下面的 API,即可获取全部的 type,下面的例子中 doc 就是 indexName 索引下的一个 type:
GET http://es127.0.0.1:9200/indexName/_mappings
-----------------------------------------------
{
indexName: - {
mappings: - {
doc: - {
_all: + {... },
dynamic_date_formats: + [... ],
dynamic_templates: + [... ],
properties: + {... }
}
}
}
}
8、索引模板中根据字段值设置别名
设置索引模板的时候,别名可以使用 Query 条件来进行匹配。
PUT _template/template_1
{
"index_patterns" : ["te*"],
"settings" : {
"number_of_shards" : 1
},
"aliases" : {
"alias2" : {
"filter" : {
"term" : {"user" : "kimchy" }
},
"routing" : "kimchy"
},
"{index}-alias" : {}
}
}
9、索引模板设置默认时间匹配格式
ES 默认是不会将 yyyy-MM-dd HH:mm:ss 识别为时间的,可以通过在索引模板进行如下设置实现多种时间格式的识别:
"mappings": {
"doc": {
"dynamic_date_formats": ["yyyy-MM-dd HH:mm:ss||strict_date_optional_time||epoch_millis"],
10、ES 中 Merge 相关设置
Merge 是非常耗费 CPU 的操作;而且如果不是 SSD 的话,推荐将 index.merge.scheduler.max_thread_count 设置为 1;否则 ES 会启动 Math.min(3, Runtime.getRuntime().availableProcessors() / 2) 个线程进行 Merge 操作;这样大部分机械硬盘的磁盘 IO 都很难承受,就可能出现阻塞。
"index": {
"refresh_interval": "5s",
"number_of_shards": "3",
"max_result_window": 10000,
"translog": {
"flush_threshold_size": "500mb",
"sync_interval": "30s",
"durability": "async"
},
"merge": {
"scheduler": {
"max_merge_count": "100",
"max_thread_count": "1"
}
},
11、mapping 中 enabled store index 参数
- enabled:默认是true,只用于 mapping 中的 object 字段类型;当设置为 false 时,其作用是使 es 不去解析该字段,并且该字段不能被查询和 store,只有在 source 中才能看到,设置 enabled 为 false,可以不设置字段类型,默认类型为 object;
- store:默认 false,store 参数的功能和 source 有一些相似,我们的数据默认都会在 source 中存在,但我们也可以将数据 store 起来;当我们使用
copy_to
参数时,copy_to
的目标字段并不会在 source 中存储,此时 store 就派上用场了; - index:默认是 true,当设置为 false,表明该字段不能被查询,如果查询会报错。
12、ES 图片搜索
- 可以借助局部敏感 LSH 或者 pHash 来实现:https://stackoverflow.com/questions/32785803
- Github 也有一个开源项目使用了多种 Hash 算法借助 ES 来实现图片搜索:https://github.com/usc-isi-i2/elasticsearch-image-features
13、Term 聚合根据子聚合结果排序
GET /_search
{
"aggs" : {
"genres" : {
"terms" : {
"field" : "genre",
"order" : { "playback_stats.max" : "desc" }
},
"aggs" : {
"playback_stats" : { "stats" : { "field" : "play_count" } }
}
}
}
}
三、社区文章精选
ELK 使用小技巧(第 2 期)
Elasticsearch • rochy 发表了文章 • 1 个评论 • 7043 次浏览 • 2018-11-17 18:36
ELK Tips 主要介绍一些 ELK 使用过程中的小技巧,内容主要来源为 Elastic 中文社区。
一、Logstash
1、Filebeat :Non-zero metrics in the last 30s
- 问题表现:Filebeat 无法向 Elasticsearch 发送日志数据;
- 错误信息:
INFO [monitoring] 1og/log.go:124 Non-zero metrics in the last 30s
; - 社区反馈:在 input 和 output 下面添加属性 enabled:true。
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/*.log
output.elasticsearch:
hosts: ["https://localhost:9200"]
username: "filebeat_internal"
password: "YOUR_PASSWORD"
enabled: true
input 和 output 下 enabled 属性默认值为 true,因此怀疑另有其因。
2、Logstash 按月生成索引
output {
if [type] == "typeA"{
elasticsearch {
hosts => "127.0.0.1:9200"
index => "log_%{+YYYY_MM}"
}
}
}
按照日的原理类似:%{+YYYY.MM.dd}
3、Filebeat 通过配置删除特定字段
Filebeat 实现了类似 Logstash 中 filter 的功能,叫做处理器(processors),processors 种类不多,尽可能在保持 Filebeat 轻量化的基础上提供更多常用的功能。
下面列几种常用的 processors:
add_cloud_metadata
:添加云服务器的 meta 信息;add_locale
:添加本地时区;decode_json_fields
:解析并处理包含 Json 字符串的字段;drop_event
:丢弃符合条件的消息事件;drop_fields
:删除符合条件的字段;include_fields
:选择符合条件的字段;rename
:字段重命名;add_kubernetes_metadata
:添加 k8s 的 meta 信息;add_docker_metadata
:添加容器的 meta 信息;add_host_metadata
:添加操作系统的 meta 信息;dissect
:类似与 gork 的正则匹配字段的功能;dns
:配置 filebeat 独立的 dns 解析方式;add_process_metadata
:添加进程的元信息。
processors 的使用方式:
- type: <input_type>
processors:
- <processor_name>:
when:
<condition>
<parameters>
...
4、LogStash 采集 FTP 日志文件
exec {
codec => plain { }
command => "curl ftp://server/logs.log"
interval => 3000}
}
5、Logstash docker-compose 启动失败(Permission denied)
在 docker-compose 中使用 user 选项设置使用 root 用户启动 docker,能解决权限问题。
$ cat docker-compose.yml
version: '2'
services:
logstash:
image: docker.elastic.co/logstash/logstash:6.4.2
user: root
command: id
6、Metricize filter plugin
将一条消息拆分为多条消息。
# 原始信息
{
type => "type A"
metric1 => "value1"
metric2 => "value2"
}
# 配置信息
filter {
metricize {
metrics => [ "metric1", "metric2" ]
}
}
# 最终输出
{ {
type => "type A" type => "type A"
metric => "metric1" metric => "metric2"
value => "value1" value => "value2"
} }
二、Elasticsearch
1、ES 倒排索引内部结构
Lucene 的倒排索引都是按照字段(field)来存储对应的文档信息的,如果 docName 和 docContent 中有“苹果”这个 term,就会有这两个索引链,如下所示:
docName:
"苹果" -> "doc1, doc2, doc3..."
docContent:
"苹果" -> "doc2, doc4, doc6..."
2、Jest 和 RestHighLevelClient 哪个好用点
RestHighLevelClient 是官方组件,会一直得到官方的支持,且会与 ES 保持同步更新,推荐使用官方的高阶 API。
Jest 由于是社区维护,所以更新会有一定延迟,目前最新版对接 ES6.3.1,近一个月只有四个 issue,说明整体活跃度较低,因此不推荐使用。
此外推荐一份 TransportClient 的中文使用手册,翻译的很不错:https://github.com/jackiehff/elasticsearch-client-java-api-cn。
3、ES 单分片使用 From/Size 分页遇到重复数据
常规情况下 ES 单分片使用 From/Size 是不会遇到数据重复的,数据重复的可能原因有:
- 没有添加排序;
- 添加了按得分排序,但是查询语句全部为 filter 过滤条件(此时得分都一致);
- 添加了排序,但是有索引中文档的新增、修改、删除等操作。
对于多分片,推荐添加 preference 参数来实现分页结果的一致性。
4、The number of object passed must be even but was [1]
ES 在调用 setSource 的时候传入 Json 对象后会报错:The number of object passed must be even but was [1],此时可以推荐将 Json 对象转为 Map 集合,或者把 Json 对象转为 json 字符串,不过传入字符串的时候需要设置类型。
IndexRequest indexRequest = new IndexRequest("index", "type", "id");
JSONObject doc = new JSONObject();
//indexRequest.source(jsonObject); 错误的使用方法
//转为 Map 对象
indexRequest.source(JSONObject.parseObject((String) doc.get("json"), Map.class));
//转为 Json 字符串(声明字符串类型)
indexRequest.source(JSON.toJSONString(doc), XContentType.JSON);
5、跨集群搜索
ES 6.X 原生支持跨集群搜索,具体配置请参考:https://www.elastic.co/guide/en/kibana/current/management-cross-cluster-search.html
PUT _cluster/settings
{
"persistent": {
"cluster": {
"remote": {
"cluster_one": {
"seeds": [
"127.0.0.1:9300"
]
},
"cluster_two": {
"seeds": [
"127.0.0.1:9301"
]
},
"cluster_three": {
"seeds": [
"127.0.0.1:9302"
]
}
}
}
}
}
ES 6.5 推出了新功能,跨集群同步(Cross-cluster replication),感兴趣的可以自行了解。
6、ES 排序时设置空值排序位置
GET /_search
{
"sort" : [
{ "price" : {"missing" : "_last"} }
],
"query" : {
"term" : { "product" : "chocolate" }
}
}
7、ES 冷归档数据如何处理
使用相对低配的大磁盘机器配置为 ES 的 Warm Nodes,可以通过 index.routing.allocation.require.box_type
来设置索引是冷数据或者热数据。如果索引极少使用,可以 close 索引,然后在需要搜索的时候 open 即可。
8、ES 相似文章检测
对于大文本的去重,可以参考 SimHash 算法,通过 SimHash 可以提取到文档指纹(64位),两篇文章通过 SimHash 计算海明距离即可判断是否重复。海明距离计算,可以通过插件实现:https://github.com/joway/elasticsearch-hamming-plugin
9、Terms 聚合查询优化
- 如果只需要聚合后前 N 条记录,推荐在 Terms 聚合时添加上
"collect_mode": "breadth_first"
; - 此外可以通过设置
"min_doc_count": 10
来限制最小匹配文档数; - 如果对返回的 Term 有所要求,可以通过设置
include
和exclude
来过滤 Term; - 如果想获取全部 Term 聚合结果,但是聚合结果又很多,可以考虑将聚合分成多个批次分别取回(Filtering Values with partitions)。
10、Tomcat 字符集造成的 ES 查询无结果
两个系统连接同一个 ES 服务,配置和代码完全一致,同一个搜索条件,一个能够搜索出来东西,一个什么都搜索不出来,排查结果是因为其中一个系统的 tomcat 配置有问题,导致请求的时候乱码了,所以搜不到数据。
11、ES 索引设置默认分词器
默认情况下,如果字段不指定分词器,ES 或使用 standard 分词器进行分词;可以通过下面的设置更改默认的分词器。
2.X 支持设置默认的索引分词器(default_index)和默认的查询分词器(default_search),6.X 已经不再支持。
PUT /index
{
"settings": {
"analysis": {
"analyzer": {
"default": {
"type": "ik_max_word",
"tokenizer": "ik_max_word"
}
}
}
}
}
12、ES 中的魔法参数
- 索引名:_index
- 类型名:_type
- 文档Id:_id
- 得分:_score
- 索引排序:_doc
如果你对排序没有特别的需求,推荐使用 _doc 进行排序,例如执行 Scroll 操作时。
13、ES 延迟执行数据上卷(Rollup )
Rollup job 有个 delay 参数控制 job 执行的延迟时间,默认情况下不延迟执行,这样如果某个 interval 的数据已经聚合好了,该 interval 迟到的数据是不会处理的。
好在 rollup api 可以支持同时搜索裸索引和 rollup 过的索引,所以如果数据经常有延迟的话,可以考虑设置一个合适的 delay,比如 1h、6h 甚至 24h,这样 rollup 的索引产生会有延迟,但是能确保迟到的数据被处理。
从应用场景上看,rollup 一般是为了对历史数据做聚合存放,减少存储空间,所以延迟几个小时,甚至几天都是合理的。搜索的时候,同时搜索最近的裸索引和历史的 rollup 索引,就能将两者的数据组合起来,在给出正确的聚合结果的情况下,又兼顾了性能。
Rollup 是实验性功能,不过非常有用,特别是使用 ES 做数据仓库的场景。
14、ES6.x 获取所有的聚合结果
ES2.x 版本中,在聚合查询时,通过设置 setSize(0)
就可以获取所有的聚合结果,在ES6.x 中直接设置 setSize(Integer.MAX_VALUE)
等效于 2.x 中设置为 0。
15、ES Jar 包冲突问题
经常会遇到 ES 与业务集成时出现 Jar 包冲突问题,推荐的解决方法是使用 maven-shade-plugin
插件,该插件通过将冲突的 Jar 包更换一个命名空间的方式来解决 Jar 包的冲突问题,具体使用可以参考文章:https://www.jianshu.com/p/d9fb7afa634d。
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<relocation>
<pattern>com.google.guava</pattern>
<shadedPattern>net.luculent.elasticsearch.guava</shadedPattern>
</relocation>
<relocation>
<pattern>com.fasterxml.jackson</pattern>
<shadedPattern>net.luculent.elasticsearch.jackson</shadedPattern>
</relocation>
<relocation>
<pattern>org.joda</pattern>
<shadedPattern>net.luculent.elasticsearch.joda</shadedPattern>
</relocation>
<relocation>
<pattern>com.google.common</pattern>
<shadedPattern>net.luculent.elasticsearch.common</shadedPattern>
</relocation>
<relocation>
<pattern>com.google.thirdparty</pattern>
<shadedPattern>net.luculent.elasticsearch.thirdparty</shadedPattern>
</relocation>
</relocations>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer" />
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
16、ES 如何选择 Shard 存储文档?
ES 采用 djb2 哈希算法对要索引文档的指定(或者默认随机生成的)_id
进行哈希,得到哈希结果后对索引 shard 数目 n 取模,公式如下:hash(_id) % n
;根据取模结果决定存储到哪一个 shard 。
三、Kibana
1、在 Kiabana 的 Discovery 界面显示自定义字段
Kibana 的 Discovery 界面默认只显示 time 和 _source 两个字段,这个界面的左半部分,在 Popular 下面展示了很多,你只需要在你需要展示的字段后面点击 add 即可将自定义的字段添加到 discovery 界面。
2、filebeat 的 monitor 指标的说明
- Total:'All events newly created in the publishing pipeline'
- Emitted: 'Events processed by the output (including retries)'
- Acknowledged:'Events acknowledged by the output (includes events dropped by the output)'
- Queued:'Events added to the event pipeline queue'
四、社区文章精选
- Elastic认证考试心得
- 一文快速上手Logstash
- 当Elasticsearch遇见Kafka--Kafka Connect
- elasticsearch冷热数据读写分离
- elasticsearch优秀实践
- ELK 使用小技巧(第 1 期)
Any Code,Code Any!
扫码关注『AnyCode』,编程路上,一起前行。
Elasticsearch 安全加固 101
Elasticsearch • medcl 发表了文章 • 8 个评论 • 21746 次浏览 • 2017-01-13 13:03
- 9200的 HTTP 接口之上加上 Nginx 来提供 Http Basic-Auth 的基本的身份认证,辅助 SSL 证书进行传输层的加密,Nginx 进一步限制可接受 Verb 请求类型及可被操作的索引前缀。
- 使用 Elastic 的 X-Pack 插件,同样提供了 Http Basic-Auth 和 SSL 传输层的加密,X-Pack 还能提供内外 Elasticsearch 集群节点间的流量加密,避免旁路攻击。
sudo -u es-user ES_JAVA_OPTS="-Xms1024m -Xmx1024m" /opt/elasticsearch/bin/elasticsearc
正确设置 Elasticsearch 的数据目录
请确保 Elasticsearch 的目录分配了合理的读写权限,避免使用共享文件系统,确保只有 elasticsearch 的启动用户才能访问,同理,日志目录也一样需要正确配置,避免泄露敏感信息。
文档君:https://www.elastic.co/guide/e ... tings
定期对 Elasticsearch 进行备份
使用 Elasticsearch 提供的备份还原机制,定期对 Elasticsearch 的数据进行快照备份,以备不时之需。
文档君:https://www.elastic.co/guide/e ... .html
加上监控和预警
Elasticsearch 提供了很好的默认参数,对参数方面还做了正确性检测,bootstrap 启动检查,不准确的参数,直接不允许 Elasticsearch 启动,以至于有很多人抱怨,怎么现在部署到线上默认就需要做这么多设置才能使用呢,是的,以前启动就默认绑定了所有的网卡,集群见自动发现和相连,现在需要手动绑定局域网网卡,默认只是绑定的本机127.0.0.1的 ip,对上线来说麻烦了一点,做了这些检查也就是为了保证数据安全,以前很多的公网都能直接访问的 Elasticsearch 实例,都是因为默认设置就绑定了公网 ip,但是这些还不够,作为用户,你还需要收集各种日志和系统监控信息,及时主动掌握服务健康和资源使用情况,发现异常情况要及时处理,这里提供一些方案:
- 使用开源的 Elastic Stack 收集这些日志,可以使用 Filebeat 收集日志,Metricbeat收集系统监控信息,存进 Elasticsearch,一旦发现异常的波动,使用 Watcher 来进行预警,通过邮件或者 webhook 调用短信、微信或者电话。
- 使用其他厂商的安全监控产品。
- 使用托管的 Elasticsearch 云的产品,如 Elastic Cloud等等。