目录 (elasticsearch 基础知识汇总)
# 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"
}
}'
# 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。
# 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"
}
}
]
}'
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 级别的用例。
Elasticsearch 集群一个比较突出的问题是: 用户做一次大的查询的时候, 非常大量的读 IO 以及聚合计算导致机器 Load 升高, CPU 使用率上升, 会影响阻塞到新数据的写入, 这个过程甚至会持续几分钟。所以,可能需要仿照 MySQL 集群一样,做读写分离。1
实施方案
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"
}
}
}
}
}'
GC
[垃圾回收]
等原因会偶尔没及时响应 ping ,一般建议稍加大 Fault Detection 的超时时间。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 # 运行间隔
# curl -XPOST http://127.0.0.1:9200/logstash-2015.06.21/testlog -d '{
"date" : "1434966686000",
"user" : "chenlin7",
"mesg" : "first message into Elasticsearch"
}'
命令返回响应结果为:
{"_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"
}
}
......
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
主分片缺失
。这部分数据完全不可用。而考虑到 ES 在写入端是简单的取余算法,轮到这个分片上的数据也会持续写入报错。接口请求的时候,可以附加一个 level 参数,指定输出信息以 indices 还是 shards 级别显示。当然,一般来说,indices 级别就够了。
对不了解 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"
}
}'