PB级数据实时查询,滴滴Elasticsearch多集群架构实践

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 任务处理模型有关。

Elasticsearch 看起来是 P2P 架构,但实际上,仍然是中心化的分布式架构。

整个集群只有一个 Active Master。Master 负责整个集群的元数据管理。

集群的所有元数据保存在 ClusterState 对象中,主要包括全局的配置信息、索引信息和节点信息。只要元数据发生修改,都得由 Master 完成。

ElasticsearchMaster 的任务处理是单线程完成的,每次处理任务,涉及到 ClusterState 的改动,都会将最新的 ClusterState 对象 Publish 给集群的全部节点,并阻塞等待全部节点接受到变更消息,处理完变更任务后,才完成本次任务。

这样的架构模型导致在集群规模变大的时候出现很严重的稳定性风险:

  • 如果有节点假死,比如 JVM 内存被打满,进程还存活着,响应 Master 任务时间会很长,影响单个任务的完成时间。
  • 有大量恢复任务的时候,由于 Master 是单线程处理的,所有任务需要排队处理,产生大量的 pending_tasks。恢复时间变得很长。
  • Elasticsearch 的任务分了优先级,例如 put-mapping 任务优先级低于创建、恢复索引,如果一些业务上低优先级索引在恢复,正常索引有新字段写入时会被阻塞。
  • Master 任务处理模型,在任务执行完成后,会回调大量 Listener 处理元数据变更。其中有些回调逻辑在索引、Shard 膨胀后,会出现处理缓慢的问题,当 Shard 膨胀到 5-6w 时,一些任务处理需要 8-9s 的时间,严重影响了集群的恢复能力。

针对这些问题,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 适用的业务场景差异特别大:

  • 针对线上核心的入口搜索,一般按城市划分索引后,索引容量不大,数据没有实时写入或者实时写入 TPS 很小。比如地图 POI 数据采用离线更新的方式,外卖商家、菜品写入量也很小。但是查询的 QPS 很高,查询对 RT 的平均时间和抖动情况要求很高。
  • 针对日志检索的场景,实时写入量特别大,有些索引甚至超过了 100w/s 的 TPS,该场景对吞吐量要求很高,但对查询 QPS 和查询 RT 要求不高。
  • 针对 Binlog 数据的检索,写入量相比日志会小很多,但是对查询的复杂度、QPS 和 RT 有一定的要求。
  • 针对监控、分析类的场景,聚合查询需求会比较多,对 Elasticsearch 内存压力较大,容易引起节点的抖动和 GC。

这些场景各异,稳定性、性能要求各不相同的场景,一个 Elasticsearch 集群即使使用各种优化手段,很难全部满足需求,最好的方式还是按业务场景划分 Elasticsearch 集群。

多集群挑战

正是单集群面临了非常大的稳定性风险,我们开始规划多集群的架构。我们在设计多集群方案的时候,期望对业务方是零感知的。

写入还是经过 Kafka,Sink 服务可以将不同 Topic 的数据入到不同的 Elasticsearch 集群。

查询继续通过 Gateway 服务,而且业务方仍然像之前一样传递索引名称,而无需感知到平台内部的索引分布。所有的索引在不同集群的分布细节,均由 Gateway 服务屏蔽。

整个改造最大的挑战在于查询方式的兼容。Elasticsearch 查询索引的方式非常灵活,可以支持 * 号作为通配符匹配。

这样一个索引 Query 可能查询的是多个索引,比如有如下 3 个索引:

  • index_a
  • index_b
  • index_c

使用 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 介绍

经过调研,我们发现 Elasticsearch Tribenode 特性可以很好的满足多集群查询的特性。

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 必须以 Clientnode 加入到每个 Elasticsearch 集群,Master 的变更任务必须等待 Tribenode 的回应才能继续,可能影响到原集群的稳定性。
  • Tribenode 不会持久化 ClusterState 对象,重启时需要从每个 Elasticsearch 集群获取元数据。而在获取元数据期间,Tribenode 就已经能够提供访问,会导致查询到还在初始化中的集群索引访问失败。
  • Tribenode 连接的集群多了,初始化会变得很慢。针对该缺陷,我们平台在重启某个 Tribenode 集群时,将 Gateway 访问该集群的全部流量切到备份 Tribenode 集群解决。
  • 如果多个集群有相同的索引名称,Tribenode 只能设置一种 Perfer 规则:随机、丢弃、Prefer 指定集群。这可能带来查到不符合预期的异常。
  • 滴滴 Elasticsearch 平台通过统一管控索引,避免了同一个索引名称出现在 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 平台就像一个无限大的 Elasticsearch 集群,而无需感知索引真实的集群分布。

多集群架构实践经验

滴滴 Elasticsearch 平台多集群的架构已经演进了一年半时间,这期间也遇到一些多集群架构带来的挑战。

①Tribenode 稳定性挑战

随着集群数量越来越多,前面提到的 Tribenode 不足越来越明显,比如初始化的时间越来越长等等。

我们采取的应对策略是部署多组 Tribenode 集群,有几组连接全量的集群,互为灾备,有几组只连接核心的一些集群,用作更为重要的跨集群访问场景。

Tribenode 的 ClusterState 元数据包含了太多的索引和 Shard,Elasticsearch 的 Search 逻辑在有些 Case 处理下容易出现耗时过长的情况。

Elasticsearch 在 Client 接收到 Search 请求时,是在 Netty 的 IO 线程中完成请求转发给每个 Shard 的,低版本的 Elasticsearch 还没有限制一次 Query 的 Shard 数量。

在一些复杂的模糊索引匹配 Shard 的逻辑中,以及给每个 Shard 发送 Query 请求时,会出现较高的耗时,可能有超过 1-2s 的 Case,这会影响到该 Netty Worker 上的其他的请求,造成部分响应飙高的情况。

我们优化了 Tribenode Search 流程中一些索引、Shard 膨胀之后的耗时逻辑,解决了该问题。

②多集群配置、版本统一的挑战

在只有一个集群的时候,平台只用维护一份集群的配置和版本。当集群数量增多后,不同集群间的 _cluster settings 信息会出现部分差异。

这些差异,可能会导致集群间的负载不均,恢复速度过快或者过慢等问题,每个集群还有一份基础的索引模板配置,这里面也出现了部分差异。

这个问题目前我们还在解决中,我们计划将 Admin 服务分离成索引管理服务和集群管理服务,集群管理会专注于集群版本、配置、部署、扩容、监控等方面对 Elasticsearch 集群进行更全面的管控。

我们做的一些 Elasticsearch 源码优化,会先后在部分集群上线,这样导致了集群间的版本混乱的问题。

我们的解决方案是在 Elasticsearch 和 Lucene 内增加内部的版本号,通过公司内部的发布系统,发布 Elasticsearch 的更新,后续集群管理服务会将集群的版本管理起来。

③多集群间容量均衡的挑战

我们主要从跨集群索引迁移和容量规划解决集群间容量均衡的挑战,在单 Elasticsearch 集群的时候,数据迁移可以依赖 Elasticsearch 的 Rebalance 能力完成。

在使用多集群架构后,平台内部的 Elasticsearch 集群会出现资源分配不均的问题。

例如有些索引容量增长的很快,导致所在集群的资源紧张,有些索引数据减少,不需要占用太多资源,导致集群资源空闲。

于是产生了索引跨集群迁移的需求。针对这个需求,我们通过给索引添加版本号,解决了索引跨集群迁移问题。之后我们有文章会详细的介绍该方案。

滴滴 Elasticsearch 平台实现了索引容量的自动规划,解决了集群间的容量均衡。

Elasticsearch 平台可以动态的规划索引的容量。当一个集群容量规划不足时,平台可以动态的迁移一部分索引到空闲的集群中。

新的索引接入需求会优先接入在空闲的集群资源中。滴滴 Elasticsearch 平台是如何实现索引容量的自动规划,也请期待后续的分享。

总结

滴滴的多集群架构,最初是为了解决 Elasticsearch 单集群架构的瓶颈。为了支持多集群架构,后面的很多组件都需要考虑连接多个集群的场景,给平台架构带来了一定的复杂性。

但是多 Elasticsearch 集群带来的稳定性和隔离性的提升,它所带来的收益远远大于架构的复杂性。

改造成多集群架构后,我们扛住了 Elasticsearch 平台规模爆炸式增长,Elasticsearch 平台的规模翻了 5 倍多,多集群架构很好的支撑了业务的快速发展。

作者:魏子珺

编辑:陶家龙、孙淑娟

Image placeholder
wind_cloud
未设置
  88人点赞

没有讨论,发表一下自己的看法吧

推荐文章
架构转型先行——金融业务场景下的新一代架构实践

  赵勇中国农业银行研发中心架构管理办公室主任工程师中国农业银行研发中心架构管理办公室主任工程师,十年以上金融行业信息化架构设计与管控经验。历经互联网金融、两地三中心、分布式核心银行等大型银行系统工程

核心业务“瘦身”进行时!手把手带你搭建海量数据实时处理架构

01背景 在线交易服务平台目的是减轻核心系统计算压力和核心性能负荷压力,通过该平台可以将核心系统的交易数据实时捕获、实时计算加工、计算结果保存于SequoiaDB中。并能实时的为用户提供在线交易查询服

Mysql数据实时同步实践

关于小米内部使用的数据库你知道多少?背景Mysql由于自身简单、高效、可靠的特点,成为小米内部使用最广泛的数据库,但是当数据量达到千万/亿级别的时候,mysql的相关操作会变的非常迟缓;如果这时还有实

大神讲解微服务治理的技术演进和架构实践

摘要:随着业务的发展,规模扩大,服务越来越多,需要协调线上运行的各个服务,保障服务的SLA;基于服务调用的性能KPI数据进行容量管理,合理分配各服务的资源占用;对故障业务做服务降级、流量控制、流量迁移

ElasticSearch 亿级数据检索案例实战

一、前言数据平台已迭代三个版本,刚开始遇到很多常见的难题,终于有时间整理一些已完善的文档了,在此分享一下。希望能帮助大家少走些弯路,在此篇幅中偏重于ES的优化。关于HBase,Hadoop的设计优化估

Elasticsearch 亿级数据检索性能优化案例实战!

一、前言数据平台已迭代三个版本,从头开始遇到很多常见的难题,终于有片段时间整理一些已完善的文档,在此分享以供所需朋友实现参考,少走些弯路,在此篇幅中偏重于ES的优化,关于HBase,Hadoop的设计

高可用架构实例:在多云和多区域中穿行

Auth0为所有技术栈上的任一平台(移动,Web,本机)应用程序提供身份验证,授权和单点登录服务。身份验证对绝大多数应用程序至关重要。我们从一开始就设计了Auth0,以便它可以在任何地方运行:在我们的

Elasticsearch 7.2 在 Laravel 中实践 --经纬度及距离查询

上一篇文档中选择的扩展,该扩展已有方法whereGeoDistance查询指定经纬度范围内的数据,但是无法根据距离排序,由于依赖于laravel-scout,而该扩展并没有实现Geo的sort,但是经

MySQL 亿级数据数据库优化方案测试-银行交易流水记录的查询

作者:逸宸a链接:https://www.jianshu.com/p/cbdef47fb837对MySQL的性能和亿级数据的处理方法思考,以及分库分表到底该如何做,在什么场景比较合适?比如银行交易流水

干货 | 每天十亿级数据更新,秒出查询结果,ClickHouse在携程酒店的应用

本文转自 |携程技术中心 作者 |蔡岳毅作者简介蔡岳毅,携程酒店大数据高级研发经理,负责酒店数据智能平台研发,大数据技术创新工作。喜欢探索研究大数据的开源技术框架。一、背景1)携程酒店每天有上千表,累

亿级海量数据的实时读写和复杂查询实践

摘要:本文分享了每日亿级增量数据的实时读写、复杂查询场景实践介绍,涉及MySQL分表分库策略、数据异构、TiDB使用和优化、微服务架构等内容。  作者:黄哲铿  黄哲铿,中通商业CTO,前1号店技术总

MySQL 百万级数据量分页查询方法及其优化

作者|大神养成记原文|  http://t.cn/RnvCJnm方法1:直接使用数据库提供的SQL语句语句样式: MySQL中,可用如下方法:SELECT*FROM表名称LIMITM,N适应场景: 适

1000亿文本信息,高并发MD5查询,这么大数据量的业务怎么弄?

==提问== 沈老师,你好,想请教一个身份证信息检索的问题。公司有一个每秒5万并发查询的业务,(假设)根据身份证MD5查询身份证信息,目前有1000亿条数据,纯文本存储,前几天看你写LevelDB,请

滴滴 NewSQL 演进之 Fusion 实践

本文根据滴滴数据库存储专家余汶龙,在DTCC中国第十届数据库大会的演讲整理而成。余汶龙滴滴出行技术专家,曾经在VMware、淘宝、阿里云从事虚拟网络及存储领域的工作。现负责滴滴自研的NoSQL存储、N

HDFS3.2升级在滴滴的实践

桔妹导读:Hadoop 3的第一个稳定版本在2017年底就已经发布了,有了很多重大的改进。在HDFS方面,支持了ErasureCoding、Morethan2NameNodes、Router-Base

运营商大规模数据集群治理的实践指南

写在开头的话Q: 军哥,你们运营商行业的大规模集群,都有啥特点啊?A: 我们集群主要是承载B域、信令和互联网日志等去标识化数据,简单的说,有三个特点:1)集群规模较大:数千节点规模,近百PB数据量,日

搞个大事情,阿里如何实现上亿级数据的精准计数?

背景关系型数据库在执行计数任务时,其执行效率会随着数据量级的增长而降低;当数据量达到亿级别时,计数任务的执行效率已经低到令人不忍直视。在闲鱼团队的关系系统中,我们采用了这样一种方式来实现亿级别数据的毫

解码GaussDB:如何成为世界级数据库?

1、开源GaussDB单机版OLTP;2、成立鲲鹏智能数据产业联盟数据库产业推进组;3、1.5亿元启动基金,发起GaussDB高校金种子发展计划;4、成立十大GaussDB高校联合创新实验室;5、现场

influxDB集群模式实践

influxDB数据库以其优秀的时序数据存储和查询能力,在处理和分析类似资源监控等时序数据方面得到了广泛的应用。而influxDB自带的各种特殊函数如求平均值、标准差、随机取数据,使数据分析变得十分方

美团点评Kubernetes集群管理实践

背景作为国内领先的生活服务平台,美团点评很多业务都具有非常显著、规律的“高峰”和“低谷”特征。尤其遇到节假日或促销活动,流量还会在短时间内出现爆发式的增长。这对集群中心的资源弹性和可用性有非常高的要求

滴滴海量离线数据的在线化 — FastLoad

桔妹导读:滴滴自成立以来,有海量的数据存储在离线平台,离线数据虽然存储便宜,压缩比高,但不适用于线上使用。为此,我们提供了一键式DTS平台——FastLoad,帮助业务往在线存储系统搬运离线数据,目前

Pandas数据分析——超好用的Groupby详解

微信公众号:「Python读财」如有问题或建议,请公众号留言在日常的数据分析中,经常需要将数据根据某个(多个)字段划分为不同的群体(group)进行分析,如电商领域将全国的总销售额根据省份进行划分,分

Elasticsearch 数据写入原理分析

前言最近TL分享了下《Elasticsearch基础整理》https://www.jianshu.com/p/e82…,蹭着这个机会。写个小文巩固下,本文主要讲ES->Lucene的底层结构,然后详细

27 亿电子邮件地址外泄!ElasticSearch数据库再次中招

数据泄露事件近年来时有发生,哪怕是大体量的Facebook也未能幸免。可以说数据泄露无论是对用户还是对企业来讲都造成了一定的损失和影响。针对频频发生的数据泄露事件,不少企业都加大网络安全建设力度,也起

Elasticsearch 与传统关系型数据库的对比、倒排索引原理解析

Elasticsearch和传统关系型数据库的对比Elasticsearch中的概念与关系型数据库对比 RelationalDB Databases Tables Rows Columns 关系