三、elasticsearch架构原理

引言

从数据流向和分布的层面,介绍es的工作原理和架构设计,然后针对性的做性能优化、故障处理等。这次主要介绍es的准实时索引的实现、segment的影响、routing和replica的的读写过程,shard的allocate控制以及自动发现的配置做一些介绍。
而关于更底层的lucene的原理,在以后会做一些简单介绍。

1、准实时索引的实现

  把es的每个分片(shard)当做一个lucene,每次生成的倒排索引叫做一个段(segment),而生成segment的数据来源是放在内存中的buffer。
  但对一些实时性要求很高的场景(新入库的数据秒级能索引到),内存的数据flush到磁盘还是太慢了,所以在内存buffer刷写到磁盘还存一个文件系统缓存,es默认内存buffer每秒刷写一次到文件系统缓存中生成新的segment,
  而lucene能很快检索到文件系统缓存中的segment。最好文件系统缓存中的数据真正同步到磁盘中。
  但对于一般场景不需要特别高的实时性,可能我们更关注es文档的写入性能,可以通过_settings调大refresh参数。
POST /index_name/_settings -d ‘{“refresh_interval”:“20s”}’
-1代表完全关闭
POST /index_name/_refresh恢复默认配置
es如何保证数据一致性
   refresh只是写到文件系统缓存中,但最后一步写到实际磁盘这期间发生主机错误、硬件故障等异常怎么处理?
   es在将数据写入到内存buff时候会另外记录translog日志,如果在这期间发生异常,es会从committ位置开始,恢复整个translog文件中的记录,保证一致性。
  文件系统缓存中的segment刷到磁盘,且commit文件进行更新translog文件清空,这是flush过程。
  es默认30分钟一次flush,或者当translog大小大于512M时,主动进行flush。这两个参数分别通过index.translog.flush_threshold_periodindex.translog.flush_threshold_size参数进行控制。
为了保证数据不丢失,es默认每5s强制刷新translog日志,并且每次index、bulk、delete、update完成是,一定处罚刷新translog到磁盘上。
  如果更在意性能,可以通过设置index.translog.durability:async进行异步flush

2、segment merge的影响

  如果按照默认配置每秒将会有一个segment生成,es会在后台有独立线程做segment的合并,而小文件的merge是非常消耗资源的。 但对于5.0以上版本的es,默认归并线程和限速都是非常合理的,根本不需要自己优化。
es默认的每个segment的大小最大是5G,如果对于非常庞大的索引,可以强制大segment的合并
/index_name/_forcemerge?max_num_segments=1
但forcemerge比普通归并对资源消耗要大得多,建议不要对在写入数据的热索引执行这个操作。

3、routing和replica的读写过程

1、路由计算
  每条d写入es的doc都有其唯一id(可以自动生成,也可自己指定),每个doc写入哪个shard,将由:
shard=hash(id)%number_of_primary_shards决定
显而易见,我们在创建好索引指定shard后就不能修改shard数目了。
2、副本一致性
如果我们每个分片是2个副本,doc写入分片可以在写入主分片成功后返回,也可以在全部副本数据写入成功后返回。
通过index.write.wait_for_active_shards控制
1代表仅写完主分片返回
all代表所有副本分片都写完才返回。

4、shard的allocate控制

其实我主要想介绍es的读写分离方案
索引的创建、删除、新增副本、节点增删等操作都会触发shard的allocate
一般常见优化的策略有两种:
4.1、磁盘限额
es默认每30s定时检查数据目录使用情况,当达到数据盘85%(routing.allocation.disk.watermark.low),新索引分片不会再分配到该节点上。再达到90%会触发该节点的数据均衡(routing.allocation.disk.watermark.high).
/_cluster/settings -d ‘{
“transient”:{
“routing.allocation.disk.watermark.low”:“85%”,
“routing.allocation.disk.watermark.high”:“10gb”,
“cluster.info.update.interval”:“1m”
}
}’
4.2、热索引分片不均
  es的数据均衡策略是以各节点的分片综总数(indices_all_active)作为基准,正常情况能很好的均衡搜索压力。
当集群扩容,新加入集群的节点,分片数远低于其他节点。如果这时候有新索引的创建,es默认策略会导致新索引所有主分片几乎全部分配在这台机器上。 所以需要预先计算好索引的分片数,配置好单节点分片的限额。
比如一台5节点的集群,索引主分片10个、副本一个,平均每个节点4个分片。
/index_name/_settings -d '{“index”:{“rounting.allocation.total_shards_per_node”:“5”}}'
配置5是为了防止节点故障发生迁移。
此外cluster.routing.allocation.balance.shard节点上分配分片的权重,默认为0.45。越大越倾向节点层面均衡分片。
cluster.routing.allocation.balance.index索引层面均衡分片,默认为0.55、
对上述场景,当集群扩容时,有新索引的创建,我们更倾向于索引层面均衡分片来避免热索引分片不均。 则可以设置cluster.routing.allocation.balance.shard为0
4.3、reroute手动完成对分片的分配选择
reroute支持allocate、move、cancel,常用allocate和move
allocate :由于负载过高,有个别分片长期处于UNASSIGNED状态,可以手动分配分片。 默认只允许手动分配副本分片,所以如果是主分片故障,可以加一个allow_primary
/_cluster/reroute -d ‘{
“commands”:[{“allocate”:{“index”:“index_name”,“shard”:61,“node”:“xxx”,“allo_primary”:true}}]
}’
move: 由于负载过高,磁盘利用率过高,服务器下线。更换磁盘等。需要从节点移走部分分片
/_cluster/reroute -d ‘{
“commands”:[{“move”:{“index”:“index_name”,“shard”:0,“from_node”:“xxx”,“to_node”:“xxx”}}]
}’
/_cluster/allocation/explain -d ‘{“index”:“index_name”,“shard”:0,“primary”:false}’ 用来指定分片分配的失败原因

4.4、节点下线
/_cluster/settings -d ‘{
“transient”:{
“cluster.rounting.allocation.exclude._ip”:“xxx”
}
}’
4.5、冷热数据的读写分离
  在实际生产场景下,每天会有海量数据通过kafka或者flink等流式计算落地到es集群中,但有些业务场景需要有非常大量的聚合计算等操作导致机器load升高,而阻塞新数据的写入,导致数据积压在flink端,这个过程可能会持续几分钟导致整个数据链的不稳定,因此es仿造mysql做了读写分离。
1、3-5台机器只存放当天的数据,在elasticsearch.yml中配置node.attr.box_type:hot
2、更多的100+台机器存放历史的机器上,配置node.attr.box_type:stale
3、在模板中控制对新建索引添加hot标签:
{
“order”:0,
“template”:"*",
“settings”:{“index.routing.allocation.include.tag”:“hot”}
}

4、每天计划任务更新索引配置,将tag改为stale,索引会自动迁移到存放历史数据的100+的机器上
/index_name/_settings -d ‘{
“index”:{
“routing”:{
“allocation”:{
“include”:{
“tag”:“stale”
}
}
}
}
}’

你可能感兴趣的:(elasticsearch学习,elasticsearch,大数据生态圈)