Elasticsearch学习随笔

前言:本文内容为,我在阅读,学习elasticsearch官方文档时候的随笔。以运维工程师的角度学习elasticsearch。内容比较混乱。详细的内容,请参考官方文档。

 

1.后台运行elasticsearch
工作目录下,./bin/elasticsearch -d   

注意:由于安全问题,elasticsearch不允许root用户直接运行。因此需要用其他用户来执行程序(1.chown -R user;./bin/elasticsearch -d)


2.
节点客户端(Node client)
节点客户端作为一个非数据节点加入到本地集群中。换句话说,它本身不保存任何数据,但是它知道数据在集群中的哪个节点中,并且可以把请求转发到正确的节点。
传输客户端(Transport client)
轻量级的传输客户端可以将请求发送到远程集群。它本身不加入集群,但是它可以将请求转发到集群中的一个节点上。


3.索引数据文档

PUT /megacorp/employee/1
{
    "first_name" : "John",
    "last_name" :  "Smith",
    "age" :        25,
    "about" :      "I love to go rock climbing",
    "interests": [ "sports", "music" ]
}
 

megacorp:索引名称,employee:类型名称,1:数据的ID


4.检索文档
检索id为1的数据
GET /megacorp/employee/1

检索所有数据(默认返回前10条)
GET /megacorp/employee/_search

根据条件检索(可用于轻量级检索)
GET /megacorp/employee/_search?q=last_name:Smith

查询表达式搜索
GET /megacorp/employee/_search
{
    "query" : {
        "match" : {
            "last_name" : "Smith"
        }
    }
}

使用filter进行搜索
GET /megacorp/employee/_search
{
    "query" : {
        "bool": {
            "must": {
                "match" : {
                    "last_name" : "smith" 
                }
            },
            "filter": {
                "range" : {
                    "age" : { "gt" : 30 } 
                }
            }
        }
    }
}

全文搜索
GET /megacorp/employee/_search
{
    "query" : {
        "match" : {
            "about" : "rock climbing"
        }
    }
}
根据相关性得分进行排序输出跟“rock climbing”有关的文档

短语搜索
GET /megacorp/employee/_search
{
    "query" : {
        "match_phrase" : {   //使用match_phrase参数,精准匹配短语
            "about" : "rock climbing"
        }
    }
}

高亮搜索
GET /megacorp/employee/_search
{
    "query" : {
        "match_phrase" : {
            "about" : "rock climbing"
        }
    },
    "highlight": {
        "fields" : {
            "about" : {}
        }
    }
}

分析
GET /megacorp/employee/_search
{
  #可添加匹配条件
  "query": { 
    "match": {
      "last_name": "smith"
    }
  },
  "aggs" : {
        "all_interests" : {
            "terms" : { "field" : "interests" },
            #分级汇总
            "aggs" : {
                "avg_age" : {
                    "avg" : { "field" : "age" }
                }
            }
        }
    }
}


5.分布式特性
Elasticsearch 尽可能地屏蔽了分布式系统的复杂性。这里列举了一些在后台自动执行的操作:
    --分配文档到不同的容器 或 分片 中,文档可以储存在一个或多个节点中
    --按集群节点来均衡分配这些分片,从而对索引和搜索过程进行负载均衡
    --复制每个分片以支持数据冗余,从而防止硬件故障导致的数据丢失
    --将集群中任一节点的请求路由到存有相关数据的节点
    --集群扩容时无缝整合新节点,重新分配分片以便从离群节点恢复


集群原理
1.健康状态
GET /_cluster/health
green
所有的主分片和副本分片都正常运行。
yellow
所有的主分片都正常运行,但不是所有的副本分片都正常运行。
red
有主分片没能正常运行。

注:单节点时,监控状态出现yellow:集群原理里,如果持有主分片的节点挂掉了,一个副本分片就会晋升为主分片的角色。那么可以看出来副本分片和主分片是不能放到一个节点上面的,可是在只有一个节点的集群里,副本分片没有办法分配到其他的节点上,所以出现所有副本分片都unassigned得情况。因为只有一个节点,如果存在主分片节点挂掉了,那么整个集群理应就挂掉了,不存在副本分片升为主分片的情况。解决办法就是,在单节点的elasticsearch集群,删除存在副本分片的索引,新建索引的副本都设为0。然后再查看集群状态。

2.创建索引
PUT /blogs
{
   "settings" : {
      #分片数量,副本数量    
      "number_of_shards" : 3, 
      "number_of_replicas" : 1
   }
}

3.单播形式加入集群
修改elasticsearch.yml文件:
node.name=node-srv1
network.host=0.0.0.0|x.x.x.x
discovery.zen.ping.unicast.hosts: ["host1", "host2:port"]


集群管理、监控与部署
监控
1.marvel监控

安装marvel
i)每一个ES安装licence、marvel插件
      进入elasticsearch/bin下,
    bash plugin install licence 
    bash plugin install marvel-agent
ii)配置elasticsearch.yml配置文件,添加action.auto_create_index: .marvel-*
iii)kibana安装marvel插件
    bash kibana plugin --install elasticsearch/marvel/latest
iv)重启ES,kibana服务
    bash elasticsearch -d
    systemctl restart kibana

2.集群健康
GET _cluster/health
{
    #集群名称
   "cluster_name": "elasticsearch_zach",   
    #集群状态   
   "status": "green",
   "timed_out": false,
       #node包括node.master、node.data两种类型,
       #参考:https://blog.csdn.net/J_bean/article/details/80147277
   "number_of_nodes": 1,
   "number_of_data_nodes": 1,
       #主分片数量
   "active_primary_shards": 10,
       #分片总量
   "active_shards": 10,
       #当前正在从一个节点迁往其他节点的分片的数量,当出现扩容或者下线node时会变动
   "relocating_shards": 0,
       #是刚刚创建的分片的个数,临时事件
   "initializing_shards": 0,
       #已经在集群状态中存在的分片,但是实际在集群里又找不着
       #通常未分配分片的来源是未分配的副本
       #如果你的集群是 red 状态,也会长期保有未分配分片    
   "unassigned_shards": 0
}

集群状态
green
所有的主分片和副本分片都已分配。你的集群是 100% 可用的。
yellow
所有的主分片已经分片了,但至少还有一个副本是缺失的。不会有数据丢失,所以搜索结果依然是完整的。不过,你的高可用性在某种程度上被弱化。如果 更多的 分片消失,你就会丢数据了。把 yellow 想象成一个需要及时调查的警告。
red
至少一个主分片(以及它的全部副本)都在缺失中。这意味着你在缺少数据:搜索只能返回部分数据,而分配到这个分片上的写入请求会返回一个异常。

进一步查询状态
level参数帮助我们进一步查询状态细节
查询索引的情况
GET _cluster/health?level=indices
查询分片状态
GET _cluster/health?level=shards

阻塞等待状态变化
你可以指定一个 wait_for_status 参数,它只有在状态达标之后才会返回。
GET _cluster/health?wait_for_status=green
用于避免网络延时导致的问题:可以用于脚本中,执行创建索引,并写入文档之间的操作。来避免因为创建需要的时间误差导致写入失败

节点监控
参考:https://www.elastic.co/guide/cn/elasticsearch/guide/current/_monitoring_individual_nodes.html#_%E7%B4%A2%E5%BC%95%E9%83%A8%E5%88%86

GET _node/stats 由于输出内容比较长,下面分段来解析重要的内容

1)开头部分
{
   "cluster_name": "elasticsearch_zach",
   "nodes": {
      "UNr6ZMf5Qk-YCPA_L18BOQ": {
         "timestamp": 1408474151742,
         "name": "Zach",
         "transport_address": "inet[zacharys-air/192.168.1.131:9300]",
         "host": "zacharys-air",
         "ip": [
            "inet[zacharys-air/192.168.1.131:9300]",
            "NONE"
         ],

节点是排列在一个哈希里,以节点的 UUID 作为键名。还有一些节点网络信息。


2)索引部分
 "indices": {
        "docs": {
           "count": 6163666,
           "deleted": 0
        },
        "store": {
           "size_in_bytes": 2301398179,
           "throttle_time_in_millis": 122850
        },

返回的统计值被归入以下部分:
    docs 展示节点内存有多少文档,包括还没有从段里清除的已删除文档数量。
    store 部分显示节点耗用了多少物理存储。这个指标包括主分片和副本分片在内。
    如果限流时间很大,那可能表明你的磁盘限流设置得过低。

"indexing": {
           "index_total": 803441,
           "index_time_in_millis": 367654,
           "index_current": 99,
           "delete_total": 0,
           "delete_time_in_millis": 0,
           "delete_current": 0
        },
        "get": {
           "total": 6,
           "time_in_millis": 2,
           "exists_total": 5,
           "exists_time_in_millis": 2,
           "missing_total": 1,
           "missing_time_in_millis": 0,
           "current": 0
        },
        "search": {
           "open_contexts": 0,
           "query_total": 123,
           "query_time_in_millis": 531,
           "query_current": 0,
           "fetch_total": 3,
           "fetch_time_in_millis": 55,
           "fetch_current": 0
        },
        "merges": {
           "current": 0,
           "current_docs": 0,
           "current_size_in_bytes": 0,
           "total": 1128,
           "total_time_in_millis": 21338523,
           "total_docs": 7241313,
           "total_size_in_bytes": 5724869463
        },    

indexing 显示已经索引了多少文档。这个值是一个累加计数器。在文档被删除的时候,数值不会下降。还要注意的是,在发生内部 索引 操作的时候,这个值也会增加,比如说文档更新。

还列出了索引操作耗费的时间,正在索引的文档数量,以及删除操作的类似统计值。
get 显示通过 ID 获取文档的接口相关的统计值。包括对单个文档的 GET 和 HEAD 请求。

search描述在活跃中的搜索(open_contexts)数量、查询的总数量、以及自节点启动以来在查询上消耗的总时间。用query_time_in_millis / query_total 计算的比值,可以用来粗略的评价你的查询有多高效。比值越大,每个查询花费的时间越多,你应该要考虑调优了。
fetch 统计值展示了查询处理的后一半流程(query-then-fetch里的fetch)。如果fetch耗时比query还多,说明磁盘较慢,或者获取了太多文档,或者可能搜索请求设置了太大的分页(比如, size: 10000 )。

merges 包括了 Lucene段合并相关的信息。它会告诉你目前在运行几个合并,合并涉及的文档数量,正在合并的段的总大小,以及在合并操作上消耗的总时间。

在你的集群写入压力很大时,合并统计值非常重要。合并要消耗大量的磁盘I/O和CPU资源。如果你的索引有大量的写入,同时又发现大量的合并数,一定要去阅读索引性能技巧。

注意:文档更新和删除也会导致大量的合并数,因为它们会产生最终需要被合并的段 碎片 。

 "filter_cache": {
           "memory_size_in_bytes": 48,
           "evictions": 0
        },
        "fielddata": {
           "memory_size_in_bytes": 0,
           "evictions": 0
        },
        "segments": {
           "count": 319,
           "memory_in_bytes": 65812120
        },
        ...
filter_cache 展示了已缓存的过滤器位集合所用的内存数量,以及过滤器被驱逐出内存的次数。过多的驱逐数可能说明你需要加大过滤器缓存的大小,或者你的过滤器不太适合缓存(比如它们因为高基数而在大量产生,就像是缓存一个 now 时间表达式)。

不过,驱逐数是一个很难评定的指标。过滤器是在每个段的基础上缓存的,而从一个小的段里驱逐过滤器,代价比从一个大的段里要廉价的多。有可能你有很大的驱逐数,但是它们都发生在小段上,也就意味着这些对查询性能只有很小的影响。

把驱逐数指标作为一个粗略的参考。如果你看到数字很大,检查一下你的过滤器,确保他们都是正常缓存的。不断驱逐着的过滤器,哪怕都发生在很小的段上,效果也比正确缓存住了的过滤器差很多。

field_data 显示 fielddata 使用的内存,用以聚合、排序等等。这里也有一个驱逐计数。和filter_cache不同的是,这里的驱逐计数是很有用的:这个数应该或者至少是接近于0。因为fielddata不是缓存,任何驱逐都消耗巨大,应该避免掉。如果你在这里看到驱逐数,你需要重新评估你的内存情况,fielddata 限制,请求语句,或者这三者。

segments 会展示这个节点目前正在服务中的 Lucene 段的数量。 这是一个重要的数字。大多数索引会有大概 50–150 个段,哪怕它们存有 TB 级别的数十亿条文档。段数量过大表明合并出现了问题(比如,合并速度跟不上段的创建)。注意这个统计值是节点上所有索引的汇聚总数。记住这点。

memory 统计值展示了 Lucene 段自己用掉的内存大小。 这里包括底层数据结构,比如倒排表,字典,和布隆过滤器等。太大的段数量会增加这些数据结构带来的开销,这个内存使用量就是一个方便用来衡量开销的度量值。


3)os,process部分基本是系统的自描述信息,通俗易懂


4)Jvm部分
jvm 部分包括了运行 Elasticsearch 的 JVM 进程一些很关键的信息。 最重要的,它包括了垃圾回收的细节,这对你的 Elasticsearch 集群的稳定性有着重大影响。

因为垃圾回收对 Elasticsearch 是如此重要,你应该非常熟悉 node-stats API 里的这部分内容:
"jvm": {
            "timestamp": 1408556438203,
            "uptime_in_millis": 14457,
            "mem": {
               "heap_used_in_bytes": 457252160,
               "heap_used_percent": 44,
               "heap_committed_in_bytes": 1038876672,
               "heap_max_in_bytes": 1038876672,
               "non_heap_used_in_bytes": 38680680,
               "non_heap_committed_in_bytes": 38993920,

jvm 部分首先列出一些和 heap内存使用有关的常见统计值。你可以看到有多少heap被使用了,多少被指派了(当前被分配给进程的),以及 heap被允许分配的最大值。理想情况下,heap_committed_in_bytes应该等于heap_max_in_bytes。如果指派的大小更小,JVM最终会被迫调整 heap 大小——这是一个非常昂贵的操作。如果你的数字不相等,阅读 堆内存:大小和交换 学习如何正确的配置它。

heap_used_percent指标是值得关注的一个数字。Elasticsearch被配置为当heap达到75%的时候开始GC。如果你的节点一直>=75%,你的节点正处于 内存压力 状态。这是个危险信号,不远的未来可能就有慢 GC 要出现了。如果 heap 使用率一直 >=85%,你就麻烦了。Heap在90–95% 之间,则面临可怕的性能风险,此时最好的情况是长达 10–30s 的 GC,最差的情况就是内存溢出(OOM)异常。

   "pools": {
      "young": {
         "used_in_bytes": 138467752,
         "max_in_bytes": 279183360,
         "peak_used_in_bytes": 279183360,
         "peak_max_in_bytes": 279183360
      },
      "survivor": {
         "used_in_bytes": 34865152,
         "max_in_bytes": 34865152,
         "peak_used_in_bytes": 34865152,
         "peak_max_in_bytes": 34865152
      },
      "old": {
         "used_in_bytes": 283919256,
         "max_in_bytes": 724828160,
         "peak_used_in_bytes": 283919256,
         "peak_max_in_bytes": 724828160
      }
   }
},
新生代,幸存代,老年代等使用情况,通常并不重要

"gc": {
   "collectors": {
      "young": {
         "collection_count": 13,
         "collection_time_in_millis": 923
      },
      "old": {
         "collection_count": 0,
         "collection_time_in_millis": 0
      }
   }
}
gc 部分显示新生代和老生代的垃圾回收次数和累积时间。大多数时候你可以忽略掉新生代的次数:这个数字通常都很大。这是正常的。

与之相反,老生代的次数应该很小,而且 collection_time_in_millis 也应该很小。这些是累积值,所以很难给出一个阈值表示你要开始操心了(比如,一个跑了一整年的节点,即使很健康,也会有一个比较大的计数)。这就是像 Marvel 这类工具很有用的一个原因。GC 计数的 时间趋势 是个重要的考虑因素。

GC 花费的时间也很重要。比如,在索引文档时,一系列垃圾生成了。这是很常见的情况,每时每刻都会导致 GC。这些 GC 绝大多数时候都很快,对节点影响很小:新生代一般就花一两毫秒,老生代花一百多毫秒。这些跟 10 秒级别的 GC 是很不一样的。

我们的最佳建议是定期收集 GC 计数和时长(或者使用 Marvel)然后观察 GC 频率。你也可以开启慢 GC 日志记录,在 日志记录 小节已经讨论过。

5)线程池
Elasticsearch 在内部维护了线程池。 这些线程池相互协作完成任务,有必要的话相互间还会传递任务。通常来说,你不需要配置或者调优线程池,不过查看它们的统计值有时候还是有用的,可以洞察你的集群表现如何。

 "index": {
     "threads": 1,
     "queue": 0,
     "active": 0,
     "rejected": 0,
     "largest": 1,
     "completed": 1
  }

每个线程池会列出已配置的线程数量( threads ),当前在处理任务的线程数量( active ),以及在队列中等待处理的任务单元数量( queue )。

如果队列中任务单元数达到了极限,新的任务单元会开始被拒绝,你会在 rejected 统计值上看到它反映出来。这通常是你的集群在某些资源上碰到瓶颈的信号。因为队列满意味着你的节点或集群在用最高速度运行,但依然跟不上工作的蜂拥而入。


这里的一系列的线程池,大多数你可以忽略,但是有一小部分还是值得关注的:

indexing
普通的索引请求的线程池
bulk
批量请求,和单条的索引请求不同的线程池
get
Get-by-ID 操作
search
所有的搜索和查询请求
merging
专用于管理 Lucene 合并的线程池

5)文件系统与网络
fs,transport,http这些都相对易懂。比较好理解,简单说一下

transport 显示和 传输地址 相关的一些基础统计值。包括节点间的通信(通常是 9300 端口)以及任意传输客户端或者节点客户端的连接。

http 显示 HTTP 端口(通常是 9200)的统计值。如果你看到 total_opened 数很大而且还在一直上涨,这是一个明确信号,说明你的 HTTP 客户端里有没启用 keep-alive 长连接的。


6)断路器
跟 fielddata 断路器(在 断路器 介绍过)相关的统计值:
"fielddata_breaker": {
            "maximum_size_in_bytes": 623326003,
            "maximum_size": "594.4mb",
            "estimated_size_in_bytes": 0,
            "estimated_size": "0b",
            "overhead": 1.03,
            "tripped": 0
         }

这里你可以看到断路器的最大值(比如,一个请求申请更多的内存时会触发断路器)。这个部分还会让你知道断路器被触发了多少次,以及当前配置的间接开销。间接开销用来铺垫评估,因为有些请求比其他请求更难评估。

主要需要关注的是 tripped 指标。如果这个数字很大或者持续上涨,这是一个信号,说明你的请求需要优化,或者你需要添加更多内存(单机上添加,或者通过添加新节点的方式)。


集群统计
提供跟节点统计类似的信息,但是针对的是整个集群的情况,并且更加简洁
GET _cluster/stats


索引统计
以索引为中心,看统计值
单个关注的索引,多个索引,全部索引
GET my_index/_stats
GET my_index,another_index/_stats
GET _all/_stats

返回的统计信息和 节点统计 的输出很相似:search 、 fetch 、 get 、 index 、 bulk 、 segment counts 等等。

索引为中心的统计在有些时候很有用,比如辨别或验证集群中的 热门 索引,或者试图找出某些索引比其他索引更快或者更慢的原因。

实践中,节点为中心的统计还是显得更有用些。瓶颈往往是针对整个节点而言,而不是对于单个索引。因为索引一般是分布在多个节点上的,这导致以索引为中心的统计值通常不是很有用,因为它们是从不同环境的物理机器上汇聚的数据。

索引为中心的统计作为一个有用的工具可以保留在你的技能表里,但是通常它不会是第一个用的上的工具。


等待中的任务
有一些任务只能由主节点去处理,比如创建一个新的索引或者在集群中移动分片。由于一个集群中只能有一个主节点,所以只有这一节点可以处理集群级别的元数据变动。在 99.9999% 的时间里,这不会有什么问题。元数据变动的队列基本上保持为零。

在一些 罕见 的集群里,元数据变动的次数比主节点能处理的还快。这会导致等待中的操作会累积成队列。

等待中的任务 API 会给你展示队列中(如果有的话)等待的集群级别的元数据变更操作:
GET _cluster/pending_tasks
无等待任务情况
{
   "tasks": []
}

有等待任务情况
{
   "tasks": [
      {
         "insert_order": 101,
         "priority": "URGENT",
         "source": "create-index [foo_9], cause [api]",
         "time_in_queue_millis": 86,
         "time_in_queue": "86ms"
      },
      {
         "insert_order": 46,
         "priority": "HIGH",
         "source": "shard-started ([foo_2][1], node[tMTocMvQQgGCkj7QDHl3OA], [P],
         s[INITIALIZING]), reason [after recovery from gateway]",
         "time_in_queue_millis": 842,
         "time_in_queue": "842ms"
      },
  ]
}

可以看到任务都被指派了优先级(比如说URGENT要比HIGH更早的处理,任务插入的次序、操作进入队列多久,以及打算处理什么。在上面的列表中,有一个 创建索引(create-index) 和启动分片(shard-started) 的操作在等待。

Q:什么时候应该担心等待中的任务?
主节点很少会成为集群的瓶颈。唯一可能成为瓶颈的是集群状态非常大而且更新频繁。例如,如果你允许客户按照他们的意愿创建任意的动态字段,而且每个客户每天都有一个独立索引,那么你的集群状态会变得非常大。集群状态包括 ( 但不限于 )所有索引及其类型,以及每个索引的全部字段。
所以如果你有 100000 客户,然后每个客户平均有1000个字段,而且数据有90天的保留期—这就有九十亿个字段需要保存在集群状态中。不管它何时发生变更,所有的节点都需要被通知。主节点必须处理这些变动,这需要不小的CPU开销,加上推送更新的集群状态到所有节点的网络开销。
这就是那些可以看到集群状态操作队列上涨的集群。没有简单的办法可以解决这个问题,不过你有三个选择:
    --使用一个更强大的主节点。不幸的是,这种垂直扩展只是延迟这种必然结果出现而已。
    --通过某些方式限定文档的动态性质来限制集群状态的大小。
    --到达某个阈值后组建另外一个集群。

cat API
用 Linux 的 cat 命令命名,这些 API 也就设计成像 *nix 命令行工具一样工作了。
 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值