Elasticsearch 是基于 Lucene 实现的分布式搜索引擎,提供了海量数据实时检索和分析能力。Elastic 公司开源的一系列产品组成的Elastic Stack,可以为日志服务、搜索引擎、系统监控等提供简单、易用的解决方案。 滴滴 Elasticsearch 简介滴滴2016年初开始构建Elasticsearch平台,如今已经发展到超过3500+Elasticsearch实例,超过5PB的数据存储,峰值写入tps超过了2000w/s的超大规模。 Elasticsearch在滴滴有着非常丰富的使用场景,例如线上核心的打车地图搜索,客服、运营的多维度查询,滴滴日志服务等近千个平台用户。 超大的规模和丰富的场景给滴滴Elasticsearch平台带来了极大的挑战,我们在这期间积累了丰富经验,也取得了一些成果。本文给大家分享下滴滴在Elasticsearch多集群架构的实践。 单集群架构瓶颈介绍单集群架构瓶颈前,先来看下滴滴Elasticsearch单集群的架构。 滴滴Elasticsearch单集群架构滴滴在单集群架构的时候,写入和查询就已经通过Sink服务和Gateway服务管控起来。 | Sink服务滴滴几乎所有写入Elasticsearch的数据都是经由kafka消费入到Elasticsearch。kafka的数据包括业务log数据、mysql binlog数据和业务自主上报的数据,Sink服务将这些数据实时消费入到Elasticsearch。 最初设计Sink服务是想对写入Elasticsearch集群进行管控,保护Elasticsearch集群,防止海量的数据写入拖垮Elasticsearch,之后我们也一直沿用了Sink服务,并将该服务从Elasticsearch平台分离出去,成立滴滴Sink数据投递平台,可以从kafka或者MQ实时同步数据到Elasticsearch、HDFS、Ceph等多个存储服务。 有了多集群架构后,Elasticsearch平台可以消费一份MQ数据写入多个Elasticsearch集群,做到集群级别的容灾,还能通过MQ回溯数据进行故障恢复。 | Gateway服务所有业务的查询都是经过Gateway服务,Gateway服务实现了Elasticsearch的http restful和tcp协议,业务方可以通过Elasticsearch各语言版本的sdk直接访问Gateway服务,Gateway服务还实现了SQL接口,业务方可以直接使用SQL访问Elasticsearch平台。 Gateway服务最初提供了应用权限的管控,访问记录,限流、降级等基本能力,后面随着平台演进,Gateway服务还提供了索引存储分离、DSL级别的限流、多集群灾备等能力。 | Admin服务整个Elasticsearch平台由Admin服务统一管控起来。Admin服务提供了索引的生命周期管理,索引容量自动规划,索引健康分,集群监控等丰富的平台能力,以及为Sink、Gateway服务提供索引、权限等元数据信息。 Elasticsearch单集群瓶颈随着滴滴Elasticsearch平台规模的快速发展,Elasticsearch集群越来越大,最大的时候,是由几百台物理机组成集群,当时集群共 3000+ 的索引,超过了 50000 个 shard,集群总容量达到了PB级别。超大的Elasticsearch集群面临了很大的稳定性风险,这些风险主要来自于以下三个方面:
Elasticsearch架构瓶颈Elasticsearch架构在集群变大到一定的规模会遇到瓶颈,瓶颈主要跟Elasticsearch任务处理模型有关。 Elasticsearch看起来是p2p架构,但实际上,仍然是中心化的分布式架构。整个集群只有一个active master。master负责整个集群的元数据管理。集群的所有元数据保存在ClusterState对象中,主要包括全局的配置信息、索引信息和节点信息。只要元数据发生修改,都得由master完成。 Elasticsearchmaster的任务处理是单线程完成的,每次处理任务,涉及到ClusterState的改动,都会将最新的ClusterState对象publish给集群的全部节点,并阻塞等待全部节点接受到变更消息,处理完变更任务后,才完成本次任务。 这样的架构模型导致在集群规模变大的时候出现很严重的稳定性风险。
针对这些问题,Elasticsearch也在不断优化,针对相同类型的任务,比如put-mapping任务,master会一次性处理所有堆积在队列里的相同任务。ClusterState对象只传递diff内容,优化回调listener模块的处理耗时环节等等。 但是由于整个集群的任务都集中在一个master的一个线程中处理,在线程中需要同步元数据变更给集群的每个节点,并阻塞等待全部节点同步完成。这个模型在集群规模不断膨胀时,稳定性会不断下降。 | 索引资源共享风险Elasticsearch索引是由多个shard组成,master会动态给这些shard分配节点资源。不同的索引会存在资源混部的情况。 Elasticsearch通过Shard Allocation Awareness的设计,可以将集群的节点按集合划分成不同的rack。在分配索引时可以指定rack列表,这样索引就只会分配在指定rack对应的节点列表中,从而做到物理资源的隔离。 但是实际使用中,很多容量小的索引由于占用资源有限,会混部在一些节点中。这种情况下,会因为个别索引的查询、写入量飙升,而影响到其他索引的稳定性。如果出现了节点故障,就会影响到整个集群的稳定性。 整个集群master、clientnode资源是共享的,master风险前面已经单独提及,clientnode共享带来的gc、抖动、异常问题都会影响到集群内的全部索引。 | 业务场景差异大 Elasticsearch适用的业务场景差异特别大。
这些场景各异,稳定性、性能要求各不相同的场景,一个Elasticsearch集群即使使用各种优化手段,很难全部满足需求,最好的方式还是按业务场景划分Elasticsearch集群。 多集群挑战正是单集群面临了非常大的稳定性风险,我们开始规划多集群的架构。我们在设计多集群方案的时候,期望对业务方是零感知的。 写入还是经过kafka,Sink服务可以将不同topic的数据入到不同的Elasticsearch集群。查询继续通过Gateway服务,而且业务方仍然像之前一样传递索引名称,而无需感知到平台内部的索引分布。所有的索引在不同集群的分布细节,均由Gateway服务屏蔽。 整个改造最大的挑战在于查询方式的兼容。Elasticsearch查询索引的方式非常灵活,可以支持*号作为通配符匹配。这样一个索引query可能查询的是多个索引,比如有如下3个索引:
使用index*查询的时候,可以同时查询到index_a、index_b、index_c三个索引。 Elasticsearch这种实现方式非常简单,由于一次query最终查询的是多个shard的数据,所以无论对于具体的索引,还是模糊的索引,都是先根据索引名称得到shard列表,再将多个shard的query结果merge到一起返回。 这样的使用方式,对于多集群方案就会遇到问题,比如index_a在A集群,index_b在B集群、index_c在C集群,对于index*的query,就无法在一个集群上完成。 tribenode介绍经过调研,我们发现Elasticsearchtribenode特性可以很好的满足多集群查询的特性。tribenode的实现非常巧妙。org.elasticsearch.tribe包下只有三个文件,核心类是TribeService。tribenode的核心原理就是merge每个集群的ClusterState对象成一个公共的ClusterState对象,ClusterState包含了索引、shard和节点数据分布表。而Elasticsearch的工作逻辑都是基于ClusterState元数据驱动的,所以对外看起来就是一个包含全部索引的的clientnode。 tribenode通过配置多个Elasticsearch集群地址,然后以clientnode角色分别连接每个集群,每个集群看起来会多了一个clientnode。tribenode通过该clientnode角色获取到集群的ClusterState信息,并绑定listener监听ClusterState变化。tribenode将获取的所有集群的ClusterState信息merge到一起,形成一个对外部访问使用的ClusterState对象,对外提供服务。tribenode除了注册listener和merge ClusterState,其他的所有逻辑都是复用了clientnode的代码。 可以看到tribenode的优点:
同时tribenode有些不足的地方:
正是tribenode有了这些瑕疵,Elasticsearch在高版本引入了Cross ClusterSearch的设计,Cross Cluster不会以节点的形式连接到其他集群,只是将请求代理。目前我们还在评估Cross Cluster的方案,这里不展开介绍。 多集群架构拓扑最终改造后,我们的集群架构拓扑如下: 按照不同的应用场景,平台将Elasticsearch集群划分成四种类型,Log集群、Binlog集群、文档数据集群、独立集群。公共集群一般最多100台datanode为基准组成一个集群。我们利用滴滴云实现了集群的自动化部署和弹性扩缩容,可以很方便的水平扩展集群。 Elasticsearch集群前面是多组tribenode集群,主要是为了解决tribenode的稳定性问题。 Gateway会同时连接tribenode集群和Elasticsearch集群,根据应用访问的索引列表,配置应用访问的集群名称,Gateway根据集群名称,将请求代理到指定集群访问,如果访问的是tribenode集群,则该应用可以访问到多个集群的索引。 Admin服务则管控了所有的Elasticsearch集群,以及索引和集群的对应关系。一系列功能都针对多集群做了改造。 Sink服务已经从Elasticsearch平台分离出去,成立DSink数据投递平台,DSink Manager负责管理DSink节点,DSink Manager从Elasticsearch Admin服务获取索引的元数据信息,下发给对应的DSink节点。 多集群架构实践总结| 多集群架构收益Elasticsearch多集群架构改造给Elasticsearch平台带来了如下收益:
| 多集群架构实践经验 滴滴Elasticsearch平台多集群的架构已经演进了一年半时间,这期间也遇到一些多集群架构带来的挑战。
总结滴滴的多集群架构,最初是为了解决Elasticsearch单集群架构的瓶颈。为了支持多集群架构,后面的很多组件都需要考虑连接多个集群的场景,给平台架构带来了一定的复杂性。但是多Elasticsearch集群带来的稳定性和隔离性的提升,它所带来的收益远远大于架构的复杂性。改造成多集群架构后,我们扛住了Elasticsearch平台规模爆炸式增长,Elasticsearch平台的规模翻了5倍多,多集群架构很好的支撑了业务的快速发展。 作者丨魏子珺 出品丨滴滴技术 (ID:didi_tech) — 更多推荐 — |
|