Elasticsearch的路由机制与其分片机制有着直接的关系。Elasticsearch的路由机制即是通过哈希算法,将具有相同哈希值的文档放置到同一个主分片中。这个和通过哈希算法来进行负载均衡几乎是一样的。
而Elasticsearch也有一个默认的路由算法:它会将文档的ID值作为依据将其哈希到相应的主分片上,这种算法基本上会保持所有数据在所有分片上的一个平均分布,而不会产生数据热点。
乐观并发控制:
Elasticsearch是分布式的。当文档被创建、更新或删除,文档的新版本会被复制到集群的其它节点。Elasticsearch即是同步的又是异步的,意思是这些复制请求都是平行发送的,并无序(out of sequence)的到达目的地。这就需要一种方法确保老版本的文档永远不会覆盖新的版本。在 index 、 get 、 delete 请求时,我们指出每个文档都有一个 _version 号码,这个号码在文档被改变时加一。
Elasticsearch使用这个 _version 保证所有修改都被正确排序。当一个旧版本出现在新版本之后,它会被简单的忽略。
分布式文档存储
路由文档到分片
Elasticsearch将文档存储的哪一个分片上,是根据算法:
shard = hash(routing) % number_of_primary_shards
routing 值是一个任意字符串,它默认是 _id 但也可以自定义。这个 routing
字符串通过哈希函数生成一个数字,然后除以主切片的数量得到一个余数
(remainder),余数的范围永远是 0 到 number_of_primary_shards - 1 ,这个
数字就是特定文档所在的分片
新建、索引和删除文档都是写操作,它们必须在主分片上成功完成才能复制到相关的的复制分片上。
而我们为什么会需要自定义的Routing模式呢?首先默认的Routing模式在很多情况下都是能满足我们的需求的——平均的数据分布、对我们来说是透明的、多数时候性能也不是问题。但是在我们更深入地理解我们的数据的特征之后,使用自定义的Routing模式可能会给我们带来更好的性能。
假设你有一个100个分片的索引。当一个请求在集群上执行时会发生什么呢?
1. 这个搜索的请求会被发送到一个节点
2. 接收到这个请求的节点,将这个查询广播到这个索引的每个分片上(可能是主分片,也可能是复制分片)
3. 每个分片执行这个搜索查询并返回结果
4. 结果在通道节点上合并、排序并返回给用户
因为默认情况下,Elasticsearch使用文档的ID(类似于关系数据库中的自增ID,当然,如果不指定ID的话,Elasticsearch使用的是随机值)将文档平均的分布于所有的分片上,这导致了Elasticsearch
不能确定文档的位置,所以它必须将这个请求广播到所有的100个分片上去执行。这同时也解释了为什么主分片的数量在索引创建的时候是固定下来的,并且永远不能改变。因为如果分片的数量改变了,
所有先前的路由值就会变成非法了,文档相当于丢失了。
当然在5.0中增加了Shrink接口,它可将分片数进行收缩成它的因数,如之前你是15个分片,你可以收缩成5个或者3个又或者1个,那么我们就可以想象成这样一种场景,在写入压力非常大的收集阶段,
设置足够多的索引,充分利用shard的并行写能力,索引写完之后收缩成更少的shard,提高查询性能。而自定义的Routing模式,可以使我们的查询更具目的性。我们不必盲目地去广播查询请求,取而代
之的是:我们要告诉Elasticsearch我们的数据在哪个分片上。
而当你采集的日志数据有明显的地域性,如数据来自北京、河北、浙江、广东等,当你只需对北京的数据进行分析时,设想下如果数据是按地域进行存储的,这样分析时需要加载的数据是不是的大减小
了;这个跟数据库的分区的做法较为类似。
curl -XPOST 'http://localhost:9200/log_201702/info?routing=beijing' -d '
{
"event": "sample",
"host": "60.11.23.222"
}'
查询时指定路由
curl -XGET 'http://localhost:9200/log_201702/info_search?routing=beijing' -d '
{
"query": {
"match_all": {}
}
}'
在大规模集群计算时,使用路由是能大大提高集群的响应速度的,路由、路由、路由重要的事情说三遍。
当然在进行日志存储时,进行分表(也是数据分区的一种实现)也是提高检索速度的一个重要法宝。
利用Elasticsearch跨表查询的功能,对指定索引集合的数据进行分析,只需要对索引名进行通配(log_2017*)就能够简单的指定分析的索引。
curl -XGET 'http://localhost:9200/log_2017*/info_search?routing=beijing' -d '
{
"query": {
"match_all": {}
}
}'
指定路由查询、跨表查询这些提高集群检索性能的利器,当前简单使用SQL均以支持
指定路由查询
select * from log_201702@beijing where host between '60.11.0.0' and '60.11.0.0';
"log_201702/beijing" SQL中from的表明中用“@”来定义路由信息
跨表查询
通配符
select * from log_2017*;
定义表的数组,用","隔开
select * from log_201701,log_201703 where host = 'xx.xx.xx.xxx';
跨表查询与指定路由的结合
select * from log_201701,log_201703@beijing where host = 'xx.xx.xx.xxx';
更多使用Elasticsearch的使用技巧请关注合众开源:
https://github.com/unimassystem