ElasticSearch 模板文件配置

首先是推荐一下参考资料

  1. 中文资料:http://kibana.logstash.es/content/elasticsearch/index.html
  2. 官方文档:https://www.elastic.co/guide/index.html
  3. 中文资料:http://es.xiaoleilu.com/

2016年3月3日:更新非文件方式模板配置和模板order覆盖问题

后面如果再写ElasticSearch(后面简称 ES)文章,重新整理一下参考文档汇总一下。

为什么采用索引模板文件

ES的http接口非常好用,索引配置其实是可以通过接口完成的。但是

你肯定不希望每次重新部署ES都重新到自己的笔记上复制粘贴配置文件,采用索引模板文件来配置ES索引,模板就和其他服务器比如:Nginx apache的conf文件,可以方便通过类似rsync等工具分发,当然将索引配置保存于数据库中也是可以的,但这里主要是说明文件的方式,比较符合运维习惯。

在什么地方放置模板配置文件?

config路径下面的templates目录,正常可能长成这样:/usr/local/elasticsearch-1.7.1/config/templates/

配置内容说明

{
"order": 10,
"myaccess": { //模板名称,用于更新和识别这个模板
"mappings": { //mappings下面是模板的具体配置了
"system": { //这里坑比较多,system只不过是一个命名空间而已,你也可以取别的名字,比如官方喜欢用tweet
"properties": {//这里面就可以放具体每个索引的配置了
"@timestamp": {//这是专门给kibana用的一个字段,时间索引
"doc_values": true,//未知
"format": "dateOptionalTime",//数据格式,也可以是Y-m-d H:i:s等等,具体可以看中文文档
"index": "not_analyzed",//常见的分析模式,analyzed 和 not_analyzed 一般来说,not_analyzed会导致无法进行分词查询,默认不写这个属性的话,就是analyzed(可分词和模糊查询)
"type": "date"//日期类型,其他常见类型包括float integer string等,具体见文档说明
},
"status": {
"index": "analyzed",
"type": "short"
},
"ua": {
"type": "string"
},
"uri": {//uri 嵌套了2级
"fields": {//第二级索引的访问方式很简单,就是uri.raw(raw是自己取的名字),这样你可以方便的对同一个字段做多种分析索引,以应对不同的查询方式
"raw": {
"index": "not_analyzed",
"type": "string"
}
},
"index": "analyzed",
"type": "string"
}
}
}
},
"settings": {
"index.number_of_replicas": 0, //副本的个数,也就是同一份数据有额外多少个拷贝,默认1,如果你本地起一个节点测试,最好改为0,因为这边如果不是0,集群会一直提示说少一个节点来放副本,这个值可以动态修改
"index.number_of_shards": 5//索引分片数量,具体作用尚未阅读文档,下面有一些通过文档介绍的理解
},
"template": "myaccess*"//什么样的索引可以采用当前的模板,这是一个通配符(wildcard 这单词会经常出现在ES中),如果我们按月分索引比如 myaccess-2015.08这种索引,就会使用这个模板。
}
}

比较常见的问题是,我新建模板要不要重启 ES?或者做一个什么reload config的操作?

当模板新建完成是不需要重启ES的,有新索引被创建,这个模板文件会被应用到这新索引当中,一旦索引建立完毕,模板和索引就没有什么太大关系了。修改模板只会导致下一个被创建的索引的改动。如果要让索引使用新的模板,需要通过API来配置。

参数index.num_of_shards

当执行一个查询时,查询用的节点服务器需要查询的数据总量是:

number_of_shards * (from + size)

就是说,如果分片为5,要查 第10页,每页30条数据,需要查询的数据就是:

5 * (270 + 30) = 1500 条

每个分片都需要查300条数据,并取最后的30条,这和MySQ limit的原理是一样的,更多的分片导致更多的CPU消耗是必然。

至于分片作用:下面节选一段

Indexes in elasticsearch are not 1:1 mappings to Lucene indexes, they are in fact sharded across a configurable number of Lucene indexes, 5 by default, with 1 replica per shard. A single machine may have a greater or lesser number of shards for a given index than other machines in the cluster. Elasticsearch tries to keep the total data across all indexes about equal on all machines, even if that means that certain indexes may be disproportionately represented on a given machine. Each shard has a configurable number of full replicas, which are always stored on unique instances. If the cluster is not big enough to support the specified number of replicas the cluster’s health will be reported as a degraded ‘yellow’ state. The basic dev setup for elasticsearch, consequently, always thinks that it’s operating in a degraded state given that by default indexes, a single running instance has no peers to replicate its data to. Note that this has no practical effect on its operation for development purposes. It is, however, recommended that elasticsearch always run on multiple servers in production environments. As a clustered database, many of data guarantees hinge on multiple nodes being available.

大体可以认为分片可以将同一个请求的负载分到集群的不同节点上。

关于大分页

从上面的shard的原理来看,大的分页查询对于集群来说,开销非常巨大。

正常对于一个搜索的应用来说,当用户无法在前三页搜索到需要的内容时,应该引导用户增加搜索条件以便缩小搜索范围,而不是不断往后翻,这样不仅服务器压力大,体验也不好。

还有什么方式来管理模板?(2016年3月3日更新)

还可以通过ES提供的接口来管理模板。这种管理方式最近用的比较多,相比之前我认为文件的管理方式来说,会更直观一些。

curl -XPUT http://127.0.0.1:9200/_template/user -d '
{
...模板配置
}'

通过上面的方式,直接更新ES集群中名称为user的模板

-如何管理?

现在用的方式是将模板保存为一个个.json文件,并且放在git库中。另外用python写一个脚本来代替curl繁琐的指令操作,脚本功能如下,这样管理起来就方便了。

Usage: utp.py [options] <template file name>

Examples:
utp.py -f 0-base.json Options:
-h, --help show this help message and exit
-a, --all 遍历所有目录的模板发送到服务器
-d, --delete 删除指定文件的模板,如果和--all一起使用,删除全部以目录中模板名相同的模板
-f FILE, --file=FILE 指定模板文件,模板文件也可以直接跟在最后
-n NODE, --node=NODE Elasticsearch 节点ip [default:127.0.0.1]
-p PORT, --port=PORT Elasticsearch 节点端口 [default:9200]

关于模板相互覆盖的问题

如果你正好在做一个ELK 日志管理的项目,应该会遇到这个问题,就是很多日志的格式其实是相同的,我们并不希望反复去写模板。处理这个问题有很多手段,而且这些手段往往需要一起使用。

  1. 模板覆盖
  2. 默认模板
  3. 动态字段

-模板覆盖

在上面的模板配置中,有一个order字段。之前我没太在意,因为项目要的模板是很特殊的,没法通用。

比如我有一个日志系统,里面要放nginx日志,而公司项目很多,并不希望公用一个索引。当我们建立模板的时候,可以建立这样几个。

  • nginx 只有mappings的配置,字段名和类型,匹配所有 *-nginx-* 的模板,order=0。
  • base 只有settings的配置,主要是配置分片规则、备份规则等等,匹配所有 * 的模板 order=0
  • 项目名模板(比如user) 基本可以是空的,匹配所有user-*的模板 order = 1(或者更高)

现在建立一个索引叫做 user-nginx-2016.03.03,系统会发现符合 * 的匹配规则,调用base模板,进行配置,然后会发现也符合-nginx-规则,调用nginx模板进行配置,最后发现符合项目名模板的配置user-*,再调用项目模板。order越大,优先权也越大,同样一个配置,系统会采用order更大的模板。

这样,当有另个项目的nginx日志过来,就不用在建立新的模板了,除非这个项目有特殊需求。

-默认模板

其实就是_default_。比如你的一个索引下面有多个type,格式相同,可以建立一个名为_default_的type。当新建任意type的时候,都会先读取这个配置。可以看下面一个代码例子。

-动态字段

有时候服务器可能传一些我们没有配置好的字段过来,比如日志系统我们希望doc_values最好能是true的时候,就是true。没有分词需求的字符串字段,不要analyze。这些都可以通过动态字段来完成。比如下面一个如果遇到整数要怎么处理。

 "mappings": {
"_default_": {
"dynamic_templates": [
{
"integer field": {
"mapping": {
"doc_values": true,
"type": "integer"
},
"match": "*",
"match_mapping_type": "integer"
}
},

参考资料

  1. *上的讨论:http://*.com/questions/23926644/how-to-configure-number-of-shards-per-cluster-in-elasticsearch
  2. 中文资料:http://kibana.logstash.es/content/elasticsearch/index.html
  3. 官方文档:https://www.elastic.co/guide/index.html
上一篇:说说正则表达式的exec方法


下一篇:MPSOC之7——开发流程uramdisk