elasticsearch 基础知识汇总

 

 


索引分片: 从策略层面,控制分片分配的选择

  • 磁盘限额 为了保护节点数据安全,ES 会定时(cluster.info.update.interval,默认 30 秒)检查一下各节点的数据目录磁盘使用状况。在达到 cluster.routing.allocation.disk.watermark.low (默认 85%)的时候,新索引分片就不会再分配到这个节点上了。在达到 cluster.routing.allocation.disk.watermark.high (默认 90%)的时候,就会触发该节点现存分片的数据均衡,把数据挪到其余节点上去。这两个值不但能够写百分比,还能够写具体的字节数。有些公司可能出于成本考虑,对磁盘使用率有必定的要求,须要适当抬高这个配置:
# curl -XPUT localhost:9200/_cluster/settings -d '{ "transient" : { "cluster.routing.allocation.disk.watermark.low" : "85%", "cluster.routing.allocation.disk.watermark.high" : "10gb", "cluster.info.update.interval" : "1m" } }'

 

  • 热索引分片不均 默认状况下,ES 集群的数据均衡策略是以各节点的分片总数(indices_all_active)做为基准的。这对于搜索服务来讲无疑是均衡搜索压力提升性能的好办法。可是对于 Elastic Stack 场景,通常压力集中在新索引的数据写入方面。正常运行的时候,也没有问题。可是当集群扩容时,新加入集群的节点,分片总数远远低于其余节点。这时候若是有新索引建立,ES 的默认策略会致使新索引的全部主分片几乎全分配在这台新节点上。整个集群的写入压力,压在一个节点上,结果极可能是这个节点直接被压死,集群出现异常。 因此,对于 Elastic Stack 场景,强烈建议你们预先计算好索引的分片数后,配置好单节点分片的限额。好比,一个 5 节点的集群,索引主分片 10 个,副本 1 份。则平均下来每一个节点应该有 4 个分片,那么就配置:
# curl -s -XPUT http://127.0.0.1:9200/logstash-2015.05.08/_settings -d '{ "index": { "routing.allocation.total_shards_per_node" : "5" } }'

注意,这里配置的是 5 而不是 4。由于咱们须要预防有机器故障,分片发生迁移的状况。若是写的是 4,那么分片迁移会失败。 
此外,另外一种方式则更加玄妙,Elasticsearch 中有一系列参数,相互影响,最终联合决定分片分配: 
cluster.routing.allocation.balance.shard 节点上分配分片的权重,默认为 0.45。数值越大越倾向于在节点层面均衡分片。 
cluster.routing.allocation.balance.index 每一个索引往单个节点上分配分片的权重,默认为 0.55。数值越大越倾向于在索引层面均衡分片。 
cluster.routing.allocation.balance.threshold 大于阈值则触发均衡操做。默认为1。html


reroute 接口

  • reroute 接口支持五种指令:allocate_replica, allocate_stale_primary, allocate_empty_primary,move 和 cancel。
  • 经常使用的通常是 allocate 和 move: 
    allocate_* 指令
  • 由于负载太高等缘由,有时候个别分片可能长期处于 UNASSIGNED 状态,咱们就能够手动分配分片到指定节点上。默认状况下只容许手动分配副本分片(即便用 allocate_replica),因此若是要分配主分片,须要单独加一个 accept_data_loss 选项:
# curl -XPOST 127.0.0.1:9200/_cluster/reroute -d '{ "commands" : [ { "allocate_stale_primary" : { "index" : "logstash-2015.05.27", "shard" : 61, "node" : "10.19.0.77", "accept_data_loss" : true } } ] }'

 

  • 由于负载太高,磁盘利用率太高,服务器下线,更换磁盘等缘由,能够会须要从节点上移走部分分片:
curl -XPOST 127.0.0.1:9200/_cluster/reroute -d '{ "commands" : [ { "move" : { "index" : "logstash-2015.05.22", "shard" : 0, "from_node" : "10.19.0.81", "to_node" : "10.19.0.104" } } ] }'

 


节点下线

  • 集群中个别节点出现故障预警等状况,须要下线,也是 Elasticsearch 运维工做中常见的状况。若是已经稳定运行过一段时间的集群,每一个节点上都会保存有数量很多的分片。这种时候经过 reroute 接口手动转移,就显得太过麻烦了。这个时候,有另外一种方式:
curl -XPUT 127.0.0.1:9200/_cluster/settings -d '{ "transient" :{ "cluster.routing.allocation.exclude._ip" : "10.0.0.1" } }'

 

Elasticsearch 集群就会自动把这个 IP 上的全部分片,都自动转移到其余节点上。等到转移完成,这个空节点就能够毫无影响的下线了。和 _ip 相似的参数还有 _host, _name 等。此外,这类参数不单是 cluster 级别,也能够是 index 级别。下一小节就是 index 级别的用例。node


冷热数据的读写分离

Elasticsearch 集群一个比较突出的问题是: 用户作一次大的查询的时候, 很是大量的读 IO 以及聚合计算致使机器 Load 升高, CPU 使用率上升, 会影响阻塞到新数据的写入, 这个过程甚至会持续几分钟。因此,可能须要仿照 MySQL 集群同样,作读写分离。1算法

实施方案apache

N 台机器作热数据的存储, 上面只放当天的数据。这 N 台热数据节点上面的 elasticsearc.yml 中配置 node.tag: hot 
以前的数据放在另外的 M 台机器上。这 M 台冷数据节点中配置 node.tag: stale 
模板中控制对新建索引添加 hot 标签: 

“order” : 0, 
“template” : “*”, 
“settings” : { 
“index.routing.allocation.require.tag” : “hot” 


天天计划任务更新索引的配置, 将 tag 更改成 stale, 索引会自动迁移到 M 台冷数据节点编程

# curl -XPUT http://127.0.0.1:9200/indexname/_settings -d' { "index": { "routing": { "allocation": { "require": { "tag": "stale" } } } } }'

 


集群自动发现

  • fd 是 fault detection
  • 考虑到节点有时候由于高负载,慢 GC [垃圾回收] 等缘由会偶尔没及时响应 ping ,通常建议稍加大 Fault Detection 的超时时间。
  • discovery.zen.ping_timeout 仅在加入或者选举 master 主节点的时候才起做用;
  • discovery.zen.fd.ping_timeout 在稳定运行的集群中,master检测全部节点,以及节点检测 master是否畅通时长期有用
discovery.zen.ping.unicast.hosts: ["es0","es1", "es2","es3","es4"] # 集群自动发现 discovery.zen.fd.ping_timeout: 120s # 超时时间(根据实际状况调整) discovery.zen.fd.ping_retries: 6 # 重试次数,防止GC[Garbage collection]节点不响应被剔除 discovery.zen.fd.ping_interval: 30s # 运行间隔

 


API 接口

数据写入

# curl -XPOST http://127.0.0.1:9200/logstash-2015.06.21/testlog -d '{ "date" : "1434966686000", "user" : "chenlin7", "mesg" : "first message into Elasticsearch" }'

命令返回响应结果为:api

{"_index":"logstash-2015.06.21","_type":"testlog","_id":"AU4ew3h2nBE6n0qcyVJK","_version":1,"created":true}

 

数据读取

# curl -XGET http://127.0.0.1:9200/logstash-2015.06.21/testlog/AU4ew3h2nBE6n0qcyVJK # curl -XGET http://127.0.0.1:9200/logstash-2015.06.21/testlog/AU4ew3h2nBE6n0qcyVJK/_source GET apache-2016.12.30/testlog/AVlPEWLkYdfL4HTWelef/_source GET apache-2016.12.30/testlog/AVlPEWLkYdfL4HTWelef?fields=user # 指定字段

数据删除

# curl -XDELETE http://127.0.0.1:9200/logstash-2015.06.21/testlog/AU4ew3h2nBE6n0qcyVJK 删除不单针对单条数据,还能够删除整个整个索引。甚至能够用通配符。 # curl -XDELETE http://127.0.0.1:9200/logstash-2015.06.0* 在 Elasticsearch 2.x 以前,能够经过查询语句删除,也能够删除某个 _type 内的数据。如今都已经再也不内置支持,改成 Delete by Query 插件。由于这种方式自己对性能影响较大!

数据更新

已经写过的数据,一样仍是能够修改的。有两种办法,一种是全量提交,即指明 _id 再发送一次写入请求。
# curl -XPOST http://127.0.0.1:9200/logstash-2015.06.21/testlog/AU4ew3h2nBE6n0qcyVJK -d '{ "date" : "1434966686000", "user" : "chenlin7", "mesg" " "first message into Elasticsearch but version 2" }' 另外一种是局部更新,使用 /_update 接口: # curl -XPOST 'http://127.0.0.1:9200/logstash-2015.06.21/testlog/AU4ew3h2nBE6n0qcyVJK/_update' -d '{ "doc" : { "user" : "someone" } }' 或者 # curl -XPOST 'http://127.0.0.1:9200/logstash-2015.06.21/testlog/AU4ew3h2nBE6n0qcyVJK/_update' -d '{ "script" : "ctx._source.user = \"someone\"" }'

 

分片存储设置

PUT /_cluster/settings{
  "transient": { "cluster.routing.allocation.disk.watermark.low": "80%", "cluster.routing.allocation.disk.watermark.high": "5gb", "cluster.info.update.interval": "1m" } }

 

搜索请求

全文搜索
# curl -XGET http://127.0.0.1:9200/logstash-2015.06.21/testlog/_search?q=first # curl -XGET http://127.0.0.1:9200/logstash-2015.06.21/testlog/_search?q=user:"chenlin7" { "took": 2, Elasticsearch 执行这个搜索的耗时,以毫秒为单位 "timed_out": false, 搜索是否超时 "_shards": { 指出多少个分片被搜索了,同时也指出了成功/失败的被搜索的shards 的数量 "total": 5, "successful": 5, "failed": 0 }, "hits" : { 搜索结果 "total" : 579, 匹配查询条件的文档的总数目 "max_score" : 0.12633952, "hits" : [ 真正的搜索结果数组(默认是前10个文档) { "_index" : "logstash-2015.06.21", "_type" : "logs", "_id" : "AVmvfgGaSF0Iy2LFN0EH", "_score" : 0.12633952, "_source" : { "user" : "chenlin7" } } ...... 

 

querystring 语法

  • 上例中,?q=后面写的,就是 querystring 语法。鉴于这部份内容会在 Kibana 上常用,这里详细解析一下语法:
  • 全文检索:直接写搜索的单词,如上例中的 first;
  • 单字段的全文检索:在搜索单词以前加上字段名和冒号,好比若是知道单词 first 确定出如今 mesg 字段,能够写做 mesg:first;
  • 单字段的精确检索:在搜索单词先后加双引号,好比 user:”chenlin7”;
  • 多个检索条件的组合:可使用 NOT, AND 和 OR 来组合检索,注意必须是大写。好比 user:(“chenlin7” OR “chenlin”) AND NOT mesg:first;
  • 字段是否存在:exists:user 表示要求 user 字段存在,missing:user 表示要求 user 字段不存在;
  • 通配符:用 ? 表示单字母,* 表示任意个字母。好比 fir?t mess*;
  • 正则:须要比通配符更复杂一点的表达式,可使用正则。好比 mesg:/mes{2}ages?/。注意 ES 中正则性能不好,并且支持的功能也不是特别强大,尽可能不要使用。ES 支持的正则语法见:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-regexp-query.html#regexp-syntax
  • 近似搜索:用 ~ 表示搜索单词可能有一两个字母写的不对,请 ES 按照类似度返回结果。好比 frist~;
  • 范围搜索:对数值和时间,ES 均可以使用范围搜索,好比:rtt:>300,date:[“now-6h” TO “now”} 等。其中,[] 表示端点数值包含在范围内,{} 表示端点数值不包含在范围内;
  • 完整语法: 
    https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-queries.html

term query 的写法数组

# curl -XGET http://127.0.0.1:9200/_search -d ' { "query": { "term": { "user": "chenlin7" } } }' 

 

集群健康状态

$ curl -XGET 127.0.0.1:9200/_cluster/health?pretty安全

  • green 绿灯,全部分片都正确运行,集群很是健康。
  • yellow 黄灯,全部主分片都正确运行,可是有副本分片缺失。这种状况意味着 ES 当前仍是正常运行的,可是有必定风险。注意,在 Kibana4 的 server 端启动逻辑中,即便是黄灯状态,Kibana 4 也会拒绝启动,死循环等待集群状态变成绿灯后才能继续运行。
  • red 红灯,有主分片缺失。这部分数据彻底不可用。而考虑到 ES 在写入端是简单的取余算法,轮到这个分片上的数据也会持续写入报错。

level 请求参数

接口请求的时候,能够附加一个 level 参数,指定输出信息以 indices 仍是 shards 级别显示。固然,通常来讲,indices 级别就够了。bash

节点状态监控接口

GC(垃圾回收)

对不了解 JVM 的 GC 的读者,这里先介绍一下 GC(垃圾收集)以及 GC 对 Elasticsearch 的影响。 
Java is a garbage-collected language, which means that the programmer does not manually manage memory allocation and deallocation. The programmer simply writes code, and the Java Virtual Machine (JVM) manages the process of allocating memory as needed, and then later cleaning up that memory when no longer needed. Java 是一个自动垃圾收集的编程语言,启动 JVM 虚拟机的时候,会分配到固定大小的内存块,这个块叫作 heap(堆)。JVM 会把 heap 分红两个组: 
Young 新实例化的对象所分配的空间。这个空间通常来讲只有 100MB 到 500MB 大小。Young 空间又分为两个 survivor(幸存)空间。当 Young 空间满,就会发生一次 young gc,还存活的对象,就被移入幸存空间里,已失效的对象则被移除。 
Old 老对象存储的空间。这些对象应该是长期存活并且在较长一段时间内不会变化的内容。这个空间会大不少,在 ES 来讲,一节点上可能就有 30GB 内存是这个空间。前面提到的 young gc 中,若是某个对象连续屡次幸存下来,就会被移进 Old 空间内。而等到 Old 空间满,就会发生一次 old gc,把失效对象移除。 
听起来很美好的样子,可是这些都是有代价的!在 GC 发生的时候,JVM 须要暂停程序运行,以便本身追踪对象图收集所有失效对象。在这期间,其余一切都不会继续运行。请求没有响应,ping 没有应答,分片不会分配…… 
固然,young gc 通常来讲执行极快,没太大影响。可是 old 空间那么大,稍慢一点的 gc 就意味着程序几秒乃至十几秒的不可用,这太危险了。 
JVM 自己对 gc 算法一直在努力优化,Elasticsearch 也尽可能复用内部对象,复用网络缓冲,而后还提供像 Doc Values 这样的特性。但无论怎么说,gc 性能老是咱们须要密切关注的数据,由于它是集群稳定性最大的影响因子。 
若是你的 ES 集群监控里发现常常有很耗时的 GC,说明集群负载很重,内存不足。严重状况下,这些 GC 致使节点没法正确响应集群之间的 ping ,可能就直接从集群里退出了。而后数据分片也随之在集群中从新迁移,引起更大的网络和磁盘 IO,正常的写入和搜索也会受到影响。服务器

集群更新节点配置

  • 刚上线的服务,最近一再的更新基础配置(硬盘)
1. 关闭分片自动均衡 PUT /_cluster/settings { "transient" : { "cluster.routing.allocation.enable" : "none" } } 2). 升级重启该节点,并确认该节点从新加入到了集群中 3). 其余节点重复第2步,升级重启。 4. 最后全部节点配置更新完成后,重启集群的shard均衡 curl -XPUT http://192.168.1.2/_cluster/settings -d' { "transient" : { "cluster.routing.allocation.enable" : "all" } }' 

 

Grafana 监控ES

Kibana 2.x

  • Sence
  • Marvel
  • 5.x 版本( x-pack )
相关文章
相关标签/搜索