
本文共 2264 字,大约阅读时间需要 7 分钟。
ElasticSearch-Routing路由简介-脑裂问题以及解决方案
什么是Routing
当使用ES的客户端client,往ES中插入一条数据,也就是创建一个Document的时候,ES就会决定该Doc具体存在于哪一个索引(index)上的哪一个分片(shard)上,而这一个过程就叫做路由。
Routing的作用
默认情况下,ES根据文档的Id来进行路由,以此来均匀分配数据。
下面是路由的默认公式:
shard_num = hash(_rounting) % num_primary_shards
参数说明:
参数 | 意义 |
---|---|
shard_num | 代表最终数据落在的shard的编号 |
_rounting | 默认为文档的Id(默认情况下Id唯一) |
num_primary_shards | 主分片数量 |
注意:
这里用到了num_primary_shards,也因此,索引在定义的时候就确定好了分片的数量,并且不可以更改,因为改了,这里的路由算法就失效了。
自定义路由
下面,上文竟然说了,_rounting默认为文档的Id,那是不是说明还可以我们自己定义路由的值呢?
举个例子:
1.创建文档,指定路由的值为hello
PUT cluster/test-type/1?routing=hello{ "title":"天气预报", "city":"杭州", "count":"西湖"}
2.但是查询的时候,也必须指定路由
GET cluster/test-type/1?routing=hello
3.term查询,指定路由
GET cluster/_search{ "query":{ "terms":{ "_routing":["hello"] } }}
4.强制查询or插入数据要指定路由,需要在索引设置的时候就配置
部分如下:
"mapping":{ "_routing":{ "required":true }}
自定义路由的问题
自定义路由,容易让数据分配不均匀,因为所有指定路由都相同的数据,全部集中在同一个shards上了,导致严重的数据倾斜。
解决自定义路由产生的数据倾斜
设置index属性:
routing_partition_size:
一旦设置后,路由的公式就不再是上文的公式,改为:
shard_num = (hash(_rounting) + hash(_id) % routing_partition_size) % num_primary_shards
并且需要注意:
- 1 < routing_partition_size < primary_shard_of_number
- 使用后,无法创建join-field关系映射
- 使用后,_routing必须开启,否则报错。
ES-脑裂问题
脑裂问题:
集群中,不同的节点对master的选择出现了分歧,出现了多个竞争master的节点,并造成主分片与副本的识别出现了分歧,最终造成操作混乱,也就是精神失常。这就是ES脑裂
产生的原因
- 内存回收:data节点上的ES进程占用的内存过大,引发JVM大规模的内存回收(常见)
- 节点负载:主节点同时扮演了master和data数据存储的角色,一旦访问量过大,造成主节点压力过大,产生高延迟,让别的节点以为你master挂了,因此开始选举新的master(实际没有挂)
- 网络问题:集群间的网络延迟问题,导致一些节点访问不到master,认为master挂了(与第二条很像,实际没有挂)
解决方案
1.更改超时相关配置:
discovery.zen.ping.timeout
默认是3s,可以适当延长,比如6s,10s一类的。一旦节点在设定的时间内,没有响应,那么就认为他挂了,如果适当的延长,就可以一定程度上降低网路延迟所造成的的脑裂问题的可能性。
2.更改选举相关配置
discovery.zen.minimum_master_nodes:1
默认为1,用于控制选举行为发生的最小的集群主节点数量
假设配置个数为n
那么同时满足以下几种情况的时候,会开始新的选举
- 备选主节点个数>=n
- 认为master挂了的主节点个数>=n
注:ES官网推荐设置的值为:n/2+1,这里的n代表的是备主节点的个数。也就是配置Node.master:true的节点
3.尽量做到角色分离:
master和data角色分离
master配置:
node.master: truenode.data: false
data配置:
node.master: falsenode.data: true
如果已经产生脑裂问题,如何解决?
重启集群
首先说明一个点:ES集群启动后,默认将第一个启动的节点(node.master为true)作为master。
这里需要注意了:
**注意启动顺序,**ES认为选举出来的节点上的分片为主分片,也就是主拷贝,ES会把这个分片上的数据分发到集群上的其他节点上,进行数据覆盖,那么假设我们第一个启动的是一个client节点呢,上面的数据还是过期的,那么第一个启动后,ES把过期的数据分发到所有节点上,并数据覆盖,那么这个后果是很严重的,造成数据的丢失。
因此建议:
- 给所有的数据重新建立索引。
- 单独启动各个节点,分析每个节点上的数据是否是重要的,并且分析他的有效性
- 最终确定一个最具有效果的节点,选择他第一个启动
- 然后把剩余的节点一并启动即可。
发表评论
最新留言
关于作者
