elasticsearch 使用事项
template的使用
刚开始的时候,每次实验都去改/etc/elasticsearch/elasticsearch.yml配置文件。事实上在template里修改settings更方便并且灵活!固然最主要的,仍是调节里面的properties设定,合理的控制store和analyze了。
template设定也有多种方法。最简单的就是和存储数据同样POST上去。长期的办法,就是写成json文件放在配置路径里。其中,default配置放在/etc/elasticsearch/下,其余配置放在/etc/elasticsearch/templates/下。举例我如今的一个templates/template-logstash.json内容以下:
- {
- "template-logstash" : {
- "template" : "logstash*",
- "settings" : {
- "index.number_of_shards" : 5,
- "number_of_replicas" : 1,
- "index" : {
- "store" : {
- "compress" : {
- "stored" : true,
- "tv": true
- }
- }
- }
- },
- "mappings" : {
- "_default_" : {
- "properties" : {
- "dynamic" : "true",
- },
- },
- "loadbalancer" : {
- "_source" : {
- "compress" : true,
- },
- "_ttl" : {
- "enabled" : true,
- "default" : "10d"
- },
- "_all" : {
- "enabled" : false
- },
- "properties" : {
- "@fields" : {
- "dynamic" : "true",
- "properties" : {
- "client" : {
- "type" : "string",
- "index" : "not_analyzed"
- },
- "domain" : {
- "type" : "string",
- "index" : "not_analyzed"
- },
- "oh" : {
- "type" : "string",
- "index" : "not_analyzed"
- },
- "responsetime" : {
- "type" : "double",
- },
- "size" : {
- "type" : "long",
- "index" : "not_analyzed"
- },
- "status" : {
- "type" : "string",
- "index" : "not_analyzed"
- },
- "upstreamtime" : {
- "type" : "double",
- },
- "url" : {
- "type" : "string",
- "index" : "not_analyzed"
- }
- }
- },
- "@source" : {
- "type" : "string",
- "index" : "not_analyzed"
- },
- "@timestamp" : {
- "type" : "date",
- "format" : "dateOptionalTime"
- },
- "@type" : {
- "type" : "string",
- "index" : "not_analyzed",
- "store" : "no"
- }
- }
- }
- }
- }
- }
注意:POST 发送的 json 内容比存储的 json 文件内容要少最外层的名字,由于名字是在 url 里体现的。
mapping简介
上面template中除了index/shard/replica以外的部分,就是mapping了,你们注意到其中的dynamic,默认状况下,index会在第一条数据进入的时候自动分析这条数据的状况,给每一个value找到最恰当的type,而后以此为该index的mapping。以后再PUT上来的数据,格式若是不符合mapping的,也能存储成功,可是就没法检索了。
mapping中关于store和compress的部分。建议是 disable 掉 _all,可是 enable 住 _source!! 若是连 _source 也 disable 掉的话,一旦你重启进程,整个 index 里除了 _id,_timestamp 和 _score 三个默认字段,啥都丢了……
API简介
ES的API,最基本的就是CRUD操做了,这部分是标准的REST,就不说了。
而后还有三个API比较重要且经常使用,分别是: bulk/count/search。
Bulk顾名思义,把多个单条的记录合并成一个大数组统一提交,这样避免一条条发送的header解析,索引频繁更新,indexing速度大大提升
Count根据POST的json,返回命中范围内的总条数。固然没POST时就直接返回该index的总条数了。
Search根据POST的json或者GET的args,返回命中范围内的数据。这是最重要的部分了。下面说说经常使用的search API:
query
一旦使用search,必须至少提供query参数,而后在这个query的基础上进行接下来其余的检索。query参数又分三类:
"match_all" : { } 直接请求所有;
"term"/"text"/"prefix"/"wildcard" : { "key" : "value" } 根据字符串搜索(严格相等/片段/前缀/匹配符);
"range" : { "@timestamp" : { "from" : "now-1d", "to" : "now" } } 根据范围搜索,若是type是时间格式,可使用内置的now表示当前,而后用-1d/h/m/s来往前推。
filter
上面提到的query的参数,在filter中也都存在。此外,还有比较重要的参数就是链接操做:
"or"/"and" : [{"range":{}}, {"prefix":""}] 两个filter的查询,交集或者合集;
"bool" : ["must":{},"must_not":{},"should":{}] 上面的and虽然更快,可是只能支持两个,超过两个的,要用 bool 方法;
"not"/"limit" : {} 取反和限定执行数。注意这个limit和mysql什么的有点不一样:它限定的是在每一个shards上执行多少条。若是你有5个shards,其实对整个index是limit了5倍大小的设定值。
另外一点比较关键的是:filter结果默认是不缓存的,若是经常使用,须要指定 "_cache" : true。
facets
facets接口能够根据query返回统计数据,最基础的是terms和statistical两种。不过在日志分析的状况下,最经常使用的是:
"histogram" : { "key_field" : "", "value_field" : "", "interval" : "" } 根据时间间隔返回柱状图式的统计数据;
"terms_stats" : { "key_field" : "", "value_field" : "" } 根据key的状况返回value的统计数据,相似group by的意思。
这里就涉及到前面mapping里为何针对每一个field都设定type的缘由了。由于 histogram 里的 key_field 只能是 dateOptionalTime 格式的,value_field 只能是 string 格式的;而 terms_stats 里的 key_field 只能是 string 格式的,value_field 只能是 numberic 格式的。
而咱们都知道,http code那些200/304/400/503神马的,看起来是数字,咱们却须要的是他们的count数据,不是算他们的平均数。因此不能由ES动态的认定为long,得指定为string。
内存和打开的文件数
若是你的elasticsearch运行在专用服务器上,经验值是分配一半内存给elasticsearch。另外一半用于系统缓存,这东西也很重要的。
你能够经过修改ES_HEAP_SIZE环境变量来改变这个设定。在启动elasticsearch以前把这个变量改到你的预期值。另外一个选择上球该elasticsearch的ES_JAVA_OPTS变量,这个变量时在启动脚本(elasticsearch.in.sh或elasticsearch.bat)里传递的。你必须找到-Xms和-Xmx参数,他们是分配给进程的最小和最大内存。建议设置成相同大小。嗯,ES_HEAP_SIZE其实就是干的这个做用。
你必须确认文件描述符限制对你的elasticsearch足够大,建议值是32000到64000之间。关于这个限制的设置,另有教程能够参见。
目录数
一个可选的作法是把全部日志存在一个索引里,而后用ttl field来确保就日志被删除掉了。不过当你日志量够大的时候,这可能就是一个问题了,由于用TTL会增长开销,优化这个巨大且惟一的索引须要太长的时间,并且这些操做都是资源密集型的。
建议的办法是基于时间作目录。好比,目录名能够是YYYY-MM-DD的时间格式。时间间隔彻底取决于你打算保留多久日志。若是你要保留一周,那一天一个目录就很不错。若是你要保留一年,那一个月一个目录可能更好点。目录不要太多,由于全文搜索的时候开销相应的也会变大。
若是你选择了根据时间存储你的目录,你也能够缩小你的搜索范围到相关的目录上。好比,若是你的大多数搜索都是关于最近的日志的,那么你能够在本身的界面上提供一个”快速搜索”的选项只检索最近的目录。
轮转和优化
移除旧日志在有基于时间的目录后变得异常简单:
$ curl -XDELETE 'http://localhost:9200/old-index-name/'
这个操做的速度很是快,和删除大小差很少的少许文件速度接近。你能够放进crontab里半夜来作。
Optimizing indices是在非高峰时间能够作的一件很不错的事情。由于它能够提升你的搜索速度。尤为是在你是基于时间作目录的状况下,更建议去作了。由于除了当前的目录外,其余都不会再改,你只须要对这些旧目录优化一次就一劳永逸了。
$ curl -XPOST 'http://localhost:9200/old-index-name/_optimize'
分片和复制
经过elasticsearch.yml或者使用REST API,你能够给每一个目录配置本身的设定。具体细节参见连接。
有趣的是分片和复制的数量。默认状况下,每一个目录都被分割成5个分片。若是集群中有一个以上节点存在,每一个分片会有一个复制。也就是说每一个目录有一共10个分片。当往集群里添加新节点的时候,分片会自动均衡。因此若是你有一个默认目录和11台服务器在集群里的时候,其中一台会不存储任何数据。
每一个分片都是一个Lucene索引,因此分片越小,elasticsearch能放进分片新数据越少。若是你把目录分割成更多的分片,插入速度更快。请注意若是你用的是基于时间的目录,你只在当前目录里插入日志,其余旧目录是不会被改变的。
太多的分片带来必定的困难——在空间使用率和搜索时间方面。因此你要找到一个平衡点,你的插入量、搜索频率和使用的硬件条件。
另外一方面,复制帮助你的集群在部分节点宕机的时候依然能够运行。复制越多,必须在线运行的节点数就能够越小。复制在搜索的时候也有用——更多的复制带来更快的搜索,同时却增长建立索引的时间。由于对猪分片的修改,须要传递到更多的复制。
映射_source和_all
Mappings定义了你的文档如何被索引和存储。你能够,好比说,定义每一个字段的类型——好比你的syslog里,消息确定是字符串,严重性能够是整数。怎么定义映射参见连接。
映射有着合理的默认值,字段的类型会在新目录的第一条文档插入的时候被自动的检测出来。不过你或许会想本身来调控这点。好比,可能新目录的第一条记录的message字段里只有一个数字,因而被检测为长整型。当接下来99%的日志里确定都是字符串型的,这样Elasticsearch就无法索引他们,只会记录一个错误日志说字段类型不对。这时候就须要显式的手动映射”message” : {“type” : “string”}。如何注册一个特殊的映射详见连接。
当你使用基于时间的目录名时,在配置文件里建立索引模板可能更适合一点。详见连接。除去你的映射,你海能够定义其余目录属性,好比分片数等等。
在映射中,你能够选择压缩文档的_source。这实际上就是整行日志——因此开启压缩能够减少索引大小,并且依赖你的设定,提升性能。经验值是当你被内存大小和磁盘速度限制的时候,压缩源文件能够明显提升速度,相反的,若是受限的是CPU计算能力就不行了。更多关于source字段的细节详见连接。
默认状况下,除了给你全部的字段分别建立索引,elasticsearch还会把他们一块儿放进一个叫_all的新字段里作索引。好处是你能够在_all里搜索那些你不在意在哪一个字段找到的东西。另外一面是在建立索引和增大索引大小的时候会使用额外更多的CPU。因此若是你不用这个特性的话,关掉它。即便你用,最好也考虑一下定义清楚限定哪些字段包含进_all里。详见连接。
刷新间隔
在文档被索引后,Elasticsearch某种意义上是近乎实时的。在你搜索查找文档以前,索引必须被刷新。默认状况下,目录是每秒钟自动异步刷新的。
刷新是一个很是昂贵的操做,因此若是你稍微增大一些这个值,你会看到很是明显提升的插入速率。具体增大多少取决于你的用户能够接受到什么程度。
你能够在你的index template里保存指望的刷新间隔值。或者保存在elasticsearch.yml配置文件里,或者经过(REST API)[http://www.elasticsearch.org/guide/reference/api/admin-indices-update-settings.html]升级索引设定。
另外一个处理办法是禁用掉自动刷新,办法是设为-1。而后用REST API手动的刷新。当你要一口气插入海量日志的时候很是有效。不过一般状况下,你通常会采用的就是两个办法:在每次bulk插入后刷新或者在每次搜索前刷新。这都会推迟他们本身自己的操做响应。
Thrift
一般时,REST接口是经过HTTP协议的,不过你能够用更快的Thrift替代它。你须要安装transport-thrift plugin同时保证客户端支持这点。好比,若是你用的是pyes Python client,只须要把链接端口从默认支持HTTP的9200改到默认支持Thrift的9500就行了。
异步复制
一般,一个索引操做会在全部分片(包括复制的)都完成对文档的索引后才返回。你能够经过index API设置复制为异步的来让复制操做在后台运行。你能够直接使用这个API,也可使用现成的客户端(好比pyes或者rsyslog的omelasticsearch),都会支持这个。
用过滤器替代请求
一般,当你搜索日志的时候,你感兴趣的是经过时间序列作排序而不是评分。这种使用场景下评分是很可有可无的功能。因此用过滤器来查找日志比用请求更适宜。由于过滤器里不会执行评分并且能够被自动缓存。二者的更多细节参见连接。
批量索引
建议使用bulk API来建立索引它比你一次给一条日志建立一次索引快多了。
主要要考虑两个事情:
最佳的批量大小。它取决于不少你的设定。若是要提及始值的话,能够参考一下pyes里的默认值,即400。
给批量操做设定时器。若是你添加日志到缓冲,而后等待它的大小触发限制以启动批量插入,千万肯定还要有一个超时限制做为大小限制的补充。不然,若是你的日志量不大的话,你可能看到从日志发布到出如今elasticsearch里有一个巨大的延时。
欢迎关注本站公众号,获取更多信息