这篇分析Elasticsearch 的部分接口:
一、容量控制
1、_split
接口
_split
接口可以在新索引中将每个主分片分裂为两个或更多分片,所以使用 split 扩容时分片总量都是成倍增加而不能逐个增加。使用
split
接口分裂分片虽 然会创建新的索引,但新索引中的数据只是通过文件系统硬连接到新索引中,所 以并不存在数据复制过程。而扩容的分片又是在本地分裂,所以不存在不同节点 间网络传输数据的开销,所以 split
扩容效率相对其他方案来说还是比较高的。 _split 接口做动态打容需要预先设置索引的
number_of_routing_shards
参数, Elasticsearch 向分片散列文档采用一致性哈希算法,这个参数实际上设置了索引 分片散列空间。所以分裂后分片数量必须是 number_of_routing_shards
的因数,
同时是
number_of_shards
的倍数。
例如,设置
number_of_routing_shards
为
12, number_of_shards
为
2
,则分 片再分裂存在 2->4->12
、
2->6->12
和
2->12
三种可能的扩容路径。分裂后分片数
量可通过
_ split
接口的
index. number_of_shards
参数设置,数量必须满足前述整 数倍的要求。上面讲解的这些规则比较抽象,下面通过创建一个具体示例来看一 下如何通过 split
接口扩容索引。 首先创建一个索引 employee,
将它的主分片数量
number_ _of _shards
设置 为 2,
散列空间
number. of. routing shards
设置为
12
。然后,通过将索引的
blocks. write 参数设置为
true,
将索引设置为只读,这是因为使用
split
接口要求索引必须 为只读。最后调用 spit
接口将
enployee
索引的分片分裂到新索引 splited_employee 中,
index.number_of_shards
参数设置为
4
,即分裂为
4
个分 片。如示例所示:
DELETE employee
PUT employee
{
"settings": {
"number_of_shards":2,
"number_of_routing_ shards":12
}
}
PUT /employee/_settings
{
"blocks.write": true
}
PUT /employee/_split/splited_employee
{
"settings": {
"index.number_of_shards":4,
"index.number_of_replicas":1,
"index.blocks.write":false
},
"aliases": {
"stu":{}
}
}
在执行成功后,可调用“
GET _cat/shards"
查看分片。在返回结果中可以看 到 employee
索引共有
4
个分片,即
2
个主分片和
2
个副本分片
;
新索引 splited_employee 会有
8
个分片,即
4
个主分片和
4
个副本分片。
split
接口在创 建新索引的同时,会将原索引的配置也一同设置到新索引中。所以 index. blocks. write 参数也会一同被复制过来,但这可能并不是我们想要的。
所以在分裂分片的同时支持通过
aliases
和
settings
设置新索引的别名和配置, 所以可以在分裂分片的同时将 index. blocks. write
参数覆盖。在示例中就将这个 参数覆盖了,同时还添加了新的别名 stu
。另外,还可以在地址中添加
copy_ settings = false 参数禁止从源索引中复制配置,但这个参数在版本
8
中有可能被 废止,所以添加这个参数会收到警告。 使用 split
接口成功分裂分片后,原索引并不会被自动删除。通过原索引和 新索引都可以查看到相同的文档数据,原索引是否删除应根据业务需要具体判断。
2、_shrink
接口
与
_split
接口相反,
_shrink
接口用于缩减索引分片。尽管它们在逻辑上正好 相反,但它们在应用时的规则基本上是一致的。比如,shrink
接口在缩减索引分 片数量时也要求原始分片数量必须是缩减后分片数量的整数倍。例如原始分片数 量为 12
,则可以按
12->6->3->1
的路径缩减,也可以按
12->4->2->1
的路径缩减。 在调用_shrink
接口前要满足两个条件,第一个条件与
_split
接口类似,就是要求 索引在缩容期间必须只读;
第二个条件有些特殊,就是要求索引所有分片
(
包括副 本分片)
都要复制一份存储在同一节点,并且要求健康状态为
green,
这可以通过 routing. allocation. require._name 指定节点名称实现。如果想要查看节点名称, 可调用“GET _nodes"
接口相看所有集群节点。 与_split
接口类似,索引在缩减后的具体分片数量可通过
shrink
接口的
index.
number_of_shards
参数设置。但它的值必须与原始分片数量保持整数比例关系, 如果不设置该参数将直接缩减为 1
个分片。如示例所示,缩减后索引分片数量为
2
,同时还清除了两项配置
:
PUT /splited_employee/_settings
{
"settings": {
"blocks.write": true
"routing.allocation.require._name":"TIAN-PC"
}
}
PUT /splited employee/_shrink/shrinked_employee?copy_settings=true
{
"settings":{
"index.routing.allocation.require.name": null,
"index.blocks.write": null,
"index.number_of_shards" :2
}
}
同样地,使用
shrink
接口缩容后会创建新索引
shrinked_employee,
原索引 和新索引都可以查询到相同的文档数据。
3、_reindex
接口
尽管
_split
接口和
shrink
接口可以对索引分片数量做扩容和缩容,但在分片 数量上有倍数要求,并且分片总量受散列空间(
即
number_of_routing_shards
参数
) 的限制。如果索引容量超出了散列空间或者有其他特殊要求,则可以按新需求创 建新的索引。Elasticsearch
提供的
_reindex
接口支持将文档从一个索引重新索引 到到另一个索引中。但显然重新索引在性能上的开销要比 _split
和
_shrink
大, 所以尽量不要使用这种办法。_reindex
接口需要两个参数
source
和
dest,
前者指 明文档来源索引而后者则指明了文档添加的新索引。例如在示例中是将 users
索 引中的文档添加到 users_copy
索引中
:
POST _reindex
{
"source" :{
"index":"users"
},
"dest": {
"index":"users_copy"
}
}
需要注意的是,在重新索引时,不会将原索引的配置信息复制到新索引中。 如果事先没有指定索引配置,重新索引时将根据默认配置创建索引及映射。另外, 使用 reindex
接口必须将索引的
_ source
字段开启。
二、缓存相关
为了提升数据检索时的性能,
Elatisearch
为索引提供了三种缓存。 第一种缓存称为节点查询缓存(Node Query Cache),
负责存储节点查询结果。 节点查询缓存是节点级别的,一个节点只有一个缓存,同一节点上的分片共享同 一缓存。 在默认情况下,节点查询缓存是开启的,可通过索引 index. queries. cache. enabled 参数关闭。节点查询缓存默认使用节点内存的
10%
作为缓存容量
上限,可通过
indices. queries. cache_ size
更改,这个参数是节点的配置而非索 引配置。第二种缓存被称为分片请求缓存(Shard Request Cache)
,负责存储分片接收 到的查询结果。分片请求缓存不会缓存查询结果的 hits
字段,也就是具体的文档
内容,它一般只缓存聚集查询的相关结果。在默认情况下,分片请求缓存也是开 启的,通过索引 index.requests cache. enable
参数关闭。另一种关闭该缓存的办 法,是在调用 search
接口时添加
request. _cache = false
参数。 分片请求缓存使用的键是作为查询条件 JSON
字符串,所以如果查询条件 JSON 串完全相同,文档的查询几乎可以达到实时。但由于
JSON
属性之间并没有
次序要求,这意味着即使
JSON
描述的是同一个对象,只要它们属性的次序不同 就不能在缓存中命中数据。这点在使用时需要格外注意。 最后一种缓存就是 text
类型字段在开启
fielddata
机制后使用的缓存,它会 将 text
类型字段提取的所有词项全部加载到内存中,以提高使用该字段做排序和 聚集运算的效率。由于 fielddata
是
text
类型对文档值机制的代替,所以这种缓 存机制天然就是开启的且不能关闭。但可通过 indices. Fielddata.cache. size
设置 这个缓存的容量,默认情况下该缓存没有容量上限。 缓存的引入使得文档检索性能得到了提升,但缓存一般会带来两个主要问题: 一是如何保证缓存数据与实际数据的一致;
另一个问题是 当缓存容量超出时如 何清理缓存。 数据一致性问题,Elasticsearch
是通过让缓存与索引刷新频率保持一致实现 的。还记得索引是准实时的吗?
索引默认情况下会以每秒
1
次的频率将文档编入 索引,Elasticsearch
会在索引更新的同时让缓存也失效,这就保证了索引数据与 缓存数据的一致性。缓存数据容量问题则是通过 LRU
的方式,将最近最少使用的 缓存条目清除。同时,Elasticsearch
还提供了一个
cache
接口用于主动清理缓存。
1、_refresh
接口
_refresh
接口用于主动刷新一个或多个索引,将已经添加的文档编入索引以 使它们在检索时可见。在调用该接口时,可以直接调用或与一个或多个索引起使 用, 还可以使用_all
刷新所有索引。
GET
索引
1/_refresh
POST _refresh
GET all/_refresh
POST
索引
1,
索引
2/_ refresh
事实上,除了使用
refresh
接口主动刷新索引外,也可以在操作文档时通过 refresh 参数刷新索引。
2、_cache
接口
_cache
接口用于主动清理缓存,在调用该接口时需要在
_cache
后附加关键 字 clear
。
_ cache
接口可以清理所有缓存,也可以清理某一索引甚至某一字段的缓存,
还可以只清理某种类型的缓存。例如
:
POST /
索引
1/_cache /clear?query=true
POST /
索引
1,
索引
2/_cache /clear?request= true
POST /
索引
1/_ cache/clear?fielddata =true&fields = notes
在示例中,
query
、
request
、
fielddata
参数分别对应于不同的缓存类型,而 fields 参数则用于定义清理哪一个字段的缓存。
三、查看运行状态
除此上述接口以外,
Elasticsearch
还提供了一组用于查看索引及分片运行情 况的接口,包括_stat
、
_shard_stores
和
_segments
等。由于它们往往在性能分析 时使用。
1、_stats
接口
_stats
接口用于查看索引上不同操作的统计数据,可以直接请求也可以与索 引名称一起使用。_stats
接口返回的统计数据非常多,如果只对其中某一组统计 数据感兴趣,可以在_stats
接口后附加统计名称。 例如以下对
stats
接口的调用 都是正确的:
GET _stats
GET _stats/store
GET kibana_sample_data_flights/_stats
GET kibana_sample_data_flights/_stats/fielddata
在
stats
接口中可以使用的统计名称及它们的含义见下面,它们在返回结果 中的含义与此相同。
docs
文档总量
store
索引存储量
indexing
索引文档的统计
get GET
查询文档的统计
search _search
接口检索文档的统计
segments
分段内存的统计
completion completion
统计
frelddata fielddata
机制使用情况统计
flush flush
统计
merge merge
统计
request_ cache reuqest_ cache
统计
refresh refresh
统计
warmer warmer
统计
translog
translog
统计
2、_segments
接口
_shard_stores
接口用于查询索引分片存储情况,而
segments
接口则用于查 看底层 Lucene
的分段情况。这两个接口都只能通过
GET
方法请求,同时都可以 针对一个或多个索引,例如:
GET _shard_stores
GET /kibana_sample_data_flights/_shard_stores
GET _segments
GET /kibana_sample_data_flights/_segments/
四、其他检索接口
我们前面的检索实际上都是围绕着
search
接口,但实际上
Elasticsearch
还 提供了许多与文档检索有关的接口。比如,如果想要查看索引中满足条件的文档 数量可以使用_count
接口,如果想要执行一组检索可以使用
msearch
接口,
1、_count
接口
Elasticsearch
提供了查看文档总数的
_ count
接口,可通过
GET
或
POST
方法 请求该接口。在请求该接口的路径上,可以添加索引、映射类型,以限定统计文 档数量的范围。所以在示例中对 count
接口的请求都是正确的
:
GET _count
POST /kibana_sample_data_logs/_count
{
"query": {
"match":{
"message": "chrome"
}
}
}
2、_msearch
接口
_msearch
接口,可以在一次接口调用中执行多次查询,可以使用
GET
或
POST 方法请求。请求体每两行为一组视为一个查询,第一行为查询头包含 index
、 search_type、
preference
和
routing
等基本信息,第二行为查询体包含具体要检 索的内容如 query
、
aggregation
等。例如
:
POST /kibana_sample_data_flights/_msearch
{}
{"query":{"match_all":{}},"from" : 0,"size" : 10 }
{}
{"query" : {"match_all" : {}}}
{"index" : "kibana_sample_data_logs" }
{"query" : {"match_all": {}}}
在示例中包含了
3
个查询,前两个查询的查询头都是空的,所以默认在请求 路径中指定的 kibana_sample_data_flights
索引中查询
;
最后一个则在查询头 中指 定了索引为kibana_sample_data_logs,
所以会在
kibana_sample_data_logs
索引中 查询。
3、_validate
接口
_validate
接口用于在不执行查询的情况下,评估一个查询是否合法可执行, 这通常用于验证执行开销比较高的查询。_validate
接口可通过
GET
或
POST
方法 请求,请求路径中必须要包含_validate/ query,
也可以在路径中添加索引名称以限 定查询执行的范围。类似_search
接口。示例
:
POST _validate/query
{
"query": {
"range":{
"AvgTicketPrice": {
"gte": 1000,
"lte": 1500
}
}
}
}
4、_field_caps
接口
_field_ caps
接口用于查看某一字段支持的功能, 主要包括字段是否可检索 以及是否可聚集等。需要查看的字段可以通过 URI
参数
fields
设置,虽然可以使 用 GET
或
POST
方法请求。在请求地址中,还可以添加索引名称以限定查询范围。
例如
:
GET _field_caps?fields=AvgTicketPrice
POST /kibana_sample_data_logs/_field_caps?fields=message,agent
五、批量接口
批量操作除了
_msearch
接口接口以外,还有
_bulk
接口和
_mget
接口。
1、_bulk
如果需要批量地对
Elasticsearch
中的文档进行操作,可以使用
_bulk
接口执 行以提升效率和性能。 _bulk
接口一组请求体,请求体一般每两个一组,对应种 对文档的操作;
第一个请求体代表操作文档的类型,而第二个请求体则代表操作 文档所需要的参数。但对于某些不需要参数的文档操作来说,则可能只有一个请 求体。操作类型包括
index
、
create
、
delete
、
update
等,其中
index
和
create 都代表创建文档,区别在于当要创建的文档存在时,create
会失败而
index
则可 以变为更新; delete
和
update
则分别代表删除和更新文档。例如
:
POST _bulk
{ "index" : {"_index": "students","_id":"10"}}
{ "name" : "smith" }
{ "delete" : {"_index": "test","_id":"5"}}
{ "create": {"_index": "test","_id":"11"}}
{ "age" : 30,"name":"Candy" }
{ "update" : {"_id" :"1","_index" : "students"} }
{ "doc": {"age" : "20"}}
2、_mget
一条一条的查询,比如说要查询
100
条数据,那么就要发送
100
次网络请求, 这个开销还是很大的,如果批量查询的话,查询 100
条数据,就只要发送
1
次网 络请求,网络请求的性能开销缩减 100
倍。 比如一般的查询是:get /open-soft/_doc/1
批量查询则是:
GET /_mget
{
"docs":[
{
"_index":" open-soft ",
"_id" : 1
},
{
"_index":" open-soft-2",
"_id" : 2
}
]
}
Elasticsearch 的接口到此分析完毕,下篇分析kibana的使用,敬请期待。