概述
Elasticsearch(ES)作为首选的开源分布式搜索分析引擎,通过一套系统轻松满足用户的日志实时分析、全文检索、时序数据分析等多种需求,大幅降低大数据时代发掘数据价值的成本。
腾讯在公司内部丰富的场景中大规模使用 ES,同时联合 Elastic 公司在腾讯云上提供内核增强版的 ES 云服务。大规模、丰富的实践场景,反推着腾讯在 ES 内核的稳定性、成本、性能等方面不断的进行演进
腾讯通过执行引擎优化、存储重构、线性扩展等一系列技术方案,对原生 ES 内核在高性能、低成本、可扩展性等方面进行了深入优化,目前单集群规模达到千级节点、万亿级吞吐。
提纲
- ES 在腾讯的广泛应用:从电商级搜索到万亿级时序数据处理
- 万亿级存储系统的架构设计
- 电商级搜索服务的平台建设
- 开源社区贡献及未来探索
益处
- 万亿级存储系统的性能 及 成本设计经验;
- 架构大规模、线性扩展的分布式系统的实践经验;
- 开源社区共建的经验。
正文
今天给大家分享的主题是腾讯万亿级 Elasticsearch 架构实践,一方面和大家去介绍一下 Elasticsearch,另一方面来和大家分享分布式系统设计过程中的这种创新实践的经验。
主要内容包含四部分:
- 一部分是 Elasticsearch 的简介
- 第二部分是技术挑战
- 第三部分是架构实践方面的工作
- 第四部分是一个收尾总结
一、Elasticsearch 简介
首先我们来看一下 Elasticsearch 的简介,Elasticsearch 也称为 ES,它是一套高性能分布式的存储系统,它运用了三个领域。
0. 应用领域
搜索引擎
比如说我们常见的 App 搜索、站内搜索、电商搜索等,它基于内部的倒排、索引、各类分词插件来满足大家的搜索需求。
可观测性
什么是可观测性呢?
是大家在运营开发过程中的日志、监控、应用性能这些基本上覆盖了应用开发过程中的所有数据,并且 ES 提供了完整的解决方案,从日志的采集、分析、可视化这些工作它都包含了,方便大家来使用。而且正因为 ES 覆盖了日志这个场景,日志体量非常大,带动了 ES 的快速发展。
安全检测
ES 提供了 SIEM,然后 Endpoint Security 从集中式和终端两个维度来帮助大家做安全检测和防御,这是 ES 使用的三大场景。
发展现状
ES 在现在发展得也非常快
- 首先近六年成为 DB-Engines 上排名第七的一个系统
- 然后在搜索领域里面常年排名在第一位
- 开源日志实时分析方面也处于一个首选的地位
- 开源状态方面有 51k 的 Star,应用状态下载方面的话有 4 亿+,而且和多个云厂商都有合作。
1.系统架构
然后我们来看一下 ES 的系统架构。
集群架构
首先是集群架构,ES 的集群架构是一个典型的中心化的架构,集群中包含主节点,通过分布式一致协议来保证 Master HA,并且控制着整个集群,数据节点用来提供数据的存储和访问,数据节点是线性可扩展的。
然后是物理的数据模型,物理数据模型上,ES 实际上是一个文档型数据库,它有类似关于数据库的表的结构,叫做 Index,Index 可以划分为 Shard,Shard 包含多个副本,打散到整个集群中去来保证数据的可扩展性。
另外,ES 集群中的副本动态可调,来满足大家对可用性和成本之间的一个平衡。
物理数据模型
然后是物理数据模型,物理数据模型大家写入 ES 中的数据,在一个 Shard 内部是怎么存储的呢?
我们来看一下,ES 实际上是一个 LSM Tree 架构的系统,写入的数据在底层会生成一个个小树,每一个小树 ES 叫做 Segment.
Segment 里面包含三类典型的数据结构,
一类是行存
一类是列存
最后一类是倒排索引
倒排索引的作用是用于条件过滤,比如说大家去做一些查询的时候,需要用索引来加速访问,比如说我们对 title 这个字段去建立索引,那么它会在写入的时候去进行分词,不可存在于 1、2 号文档中,es 存在于 1 号文档中,这样的一个过程是属于倒排索引。
行存储用来存储原始数据,用来返回用户可以看到的原始的日志监控这些信息,列存用于排序和聚合,这样的话大家在聚合的过程中可以只读取必要的列来加速性能,这是 ES 的一个底层的物理的数据模型。
查询
然后在查询层面的话,其实 ES 提供的是一个典型的不可查询的模式,就像我们搜索引擎一样,我们可以去查 title 包含 book,content 包含 es 这样的一本书,那么 es 就在里面去按照倒排索引,去找到满足条件的文档 ID 的集合,然后再对这部分文档 ID 去做处理,这是我们看到的整个系统架构方面的一个介绍。
2.腾讯应用现状
ES 在腾讯内部有非常广泛的应用环境,包含公有云、私有云和内部云。
公有云环境的话,它其实包含了大量的中小用户不同的使用场景,实际上可以把 ES 的边边角角每个地方都打磨的很成熟,
而内部云的话会有这种超大的集群,超高的压力,可以帮助我们去发现 ES 的一些潜在瓶颈、潜在的需求。
而私有云的场景下,它其实是由于网络隔离的原因,需要大家去做到标准化的交互、自动化的运营,所以对 ES 的自动化的运营是一个很好的打磨的状态。
下面我们来看看,ES 在具体几个应用领域下在腾讯的应用情况。
搜索领
首先是搜索领域,搜索领域里面,我们包含三类典型的应用,一个是电商产品的搜索,然后文档的搜索,然后是应用市场里面 App 的搜索类似这些应用场景。
搜索场景非常明显的特点是:
首先要求高性能,你必须要有十万级的 QPS、10ms 级的平响;
第二个是强相关,搜索的结果必须和用户的意图高度匹配,相当于是用户如果搜索一个苹果,可能意味着是苹果或者是苹果手机,但是你不能返回用户橘子;
第三个是高可用,用户在搜索场景下要求非常高的可用性,通常都有 4 个 9,马上双 11 到了,每一个电商其实都不能够接受自己的服务挂机一个小时,所以对高可用要求非常高。
ES 是一个轻量级的、垂直化的搜索的解决方案,这样的话大家可以基于 ES 来构造各种电商级的搜索应用
日志实时分析
其次我们来看看 ES 的第二类典型的应用场景,日志实时分析,这也是 ES 应用最多的场景。
我们可以基于系统的日志去做一些服务质量的监控,基于业务状态的日志去做一些运营的管理,基于用户行为日志来做用户画像分析、运营分析这些东西,然后在日志场景下,它有一些很明显的特点。
时序数据
第三块的话我们来看一下时序数据的应用,这也是腾讯在内部发起的一个非常大的应用场景,典型的比如说包含 Metrics 的应用,应用性能的监控,还有最新的物联网数据这一方面。
时序场景的一些特点是这样
它要求非常高的吞吐,所以对 CPU 资源消耗比较高;
第二个是它要求比较高的查询性能,比如说大家看到通常画的监控曲线,通常可能是要求十毫秒级或者几十毫秒级要画出来,你不能拖太久;
第三个是灵活、多维度的分析,讲到监控,讲到这种物联网数据,很明显是需要这种灵活的多维分析的能力。
而 ES 相比于专用型的这种时序数据库的话,它很明显的一个特点在于,它实际上可以实现类似这种专用数据库的压缩比、性能,同时简化用户的技术栈,来降低用户的运营成本、资源成本这些方面的东西。
二、技术挑战
第二部分来看看我们在这种大规模的应用环境下产生的技术挑战。
1.可用性
首先是可用性,可用性是所有分布式系统的共性问题,任何一个系统首先面临的都是可用性问题,抛开可能性去谈成本性能其实都是没有意义的,所以我们来看一下可用性方面的问题。
可用性方面,开源的 ES 早期实际上是很不稳定的,只有 2 个 9 的可用性,运营压力也非常大。
我们从整个社区的开发状态也可以看出,ES 的开发节奏非常快,但是 Bug 也相对较多一点。
从整个可用性问题的分类来看,我们可以看做
第一个是架构设计上面的不足,不管是这种超多的分片,然后超高的读写压力,或者是分布式集群里面的负载均衡,这些东西其实都属于架构设计这一块的内容。
第二部分是类似于安全攻击、误操作、自然灾害这些场景下,导致的数据丢失、网络分区这种容灾方案方面的东西。
第三块是比如说分布式死锁,一些 Master 任务饿死,在这些边缘场景或者是新特性开发过程中,引入的一些内核缺陷方面的问题。
这里面其实也有一个针对 ES 的玩笑,去年或者是更早一段时间里面,社区里面经常暴露出数据被劫持、数据被误删的一些场景,实际上典型的就是 Mongo 和 ES,所以这里面对可用性的要求非常高。
2.成本
第二块的技术挑战是在于成本方面,典型的代表是日志和时序场景。
日志和时序场景下,通常可以达到百万级甚至千万级的 TPS,随着时间的积累,存储成本可以达到 PB 级,非常高。而大家能够明显的感觉到日志和监控场景下,它的这种价值相对较低,所以整体上给大家带来一个非常明显的矛盾就是,你资源消耗非常高,但是业务价值相对较低。
我们来分析一下资源到底消耗在哪里。我们对于我们线上 Top 的大客户进行一个统计分析的时候发现,Top 的客户里面有 45% 左右的用户会保留 15 天的数据,40% 往上的用户会保留更久的数据,以 15 天为样例的话,我们来看看资源消耗的一个情况。
通常对于这类场景以单机模型为例,我们预计的是单机,需要的计算资源是 12Core,存储资源是 30TB,内存资源是 600GB,网络是 2GB 每秒。
从这个比例来看内存的瓶颈最为明显,超过了现有主流机型的一些配置,也是成本最高的地方。其次是存储成本,存储成本也非常高,大家可以看到是 30TB 的存储,而且随着时间的增长存储成本是线性增长的。最后是计算方面的一个成本,大家又会发现对于日志和时序的场景下,历史数据访问其实相对较少,对于这种场景下,大家又会感觉到我访问较少,还有这么高的成本,压力非常大。
3.性能
第三个我们来看一下性能方面的挑战,主要代表的场景是搜索场景。
搜索场景大家有一个很明显的情况是,大家通常是要求十万级的吞吐、10 秒级的 QPS,另外要求低毛刺。
低毛刺的要求就是主要在于,比如说搜索场景 99.5% 的查询要小于 100 毫秒,这样来保证好的用户的体验。第三个是高吞吐,你要达到一个十万级的 QPS 来满足这种大中型的电商搜索的需求,这是这三方面的需求。
但是用户直接使用开源 ES 的话,会遇到一些问题。
首先在于性能方面,大家会因为随机 I/O、Scan 执行速度不佳这些东西会导致延时比较高。
第二个方面的话,因为硬件异常、后台资源的抢占、GC 网络抖动这些不可控的因素,导致长尾非常明显。
第三个是吞吐达不到预期,首先单节点的吞吐已经有了上限,并且你集群的扩展性并没有达到比较好的一个线性扩展的水平。
所以这三个是我们的主要的挑战。
三、架构设计实践
接下来我们来看看,在针对这些挑战我们做的一些架构实践方面的东西,其实里面也包含了很多分布式系统设计过程的一些共性的问题。
1.可用性优化
首先我们来看看可用性问题,可能性问题的话其实非常丰富,我们先看一下整体的解决方案,然后后面有部分内容会给大家展开来介绍。
1.1 解决方案
可用性问题,首先在架构设计方面,ES 在架构设计方面对可用性的考虑还不是特别足,因为它是一个新系统逐步地发展起来,
第一个可用性很明显的在于 ES 集群扩展性方面的可用性问题,所以我们对这块可用性的方面的东西做了支持十万级的表、百万级的分片。
然后建造性方面的话,我们去支持压力过载、硬件故障这些场景下面集群的可用性的提升。
第三个是集群均衡,在集群内部多节点、节点内部多盘之间,做一个比较好的压力均衡。
此外我们还会通过容灾方案缺陷修复这些提高整个服务的可用性,最终的结果是我们的可用性从 2 个 9 提升到目前的 3 个 9、1 个 5,整个业务发展了 10 倍,但是运营压力保持不变。
2.2 集群扩展性
下面我们来展开介绍一下集群可用性方面的一些具体的工作。
首先是集群扩展性方面的内容,一是分布式的扩展瓶颈,其实 ES 在扩展性这块的瓶颈在社区里面反馈得比较明显,一方面是分片的这种扩展,当它达到 3 万分片的数,通常去做一次管理操作,一定要 15 秒的一个耗时。而当它集群规模达到 100 个节点的时候,可能会出现一些不稳定的因素。
而在腾讯内部的一些大规模的使用场景下,这些使用上限瓶颈很容易被触发到,所以我们需要去解决典型的具体的触发的现象是,
一个是比如说 Master 堵塞,因为元数据变更慢导致集群创建分片、创建表、删除表、集群均衡、节点的剔除这些所有的工作,其实都处于一个卡顿的状态,Master 就是几乎处于一个崩溃的状态。
另外一个是建表导致写入拒绝,ES 和传统的数据库不太一样,ES 的使用方式是在写入的时候进行建表,那么如果建表卡住就会导致写入请求堆积在内存里面,进而触发拒绝。按照社区的一个建议,大家通常可能采用的方式是拆分成大量的中小集群来运维,但这种方式的缺点在于运营成本高,而且资源利用率上不去。
为什么 ES 会有这么强的一个扩展性的瓶颈,其实跟 ES 的设计有关,ES 通过元数据的管理来实现最终整个集群的管理。我们以建表的过程为例,来帮助大家来分析理解一下,为什么 ES 会有这么大的扩展性瓶颈。
建表请求发给集群的 Master 节点,Master 节点接收到这个请求之后,首先做的一个工作是拷贝原来的元数据状态,全量拷贝,生成一份新的元数据状态,并且在元数据状态上去帮助大家分配分片。接着是去产生元数据的 Diff,这个 Diff 是用于后续元数据同步的分发,这个过程实际上是新版元数据跟老版元数据的全量的对比。
紧接着是一个两阶段的提交过程,这个大家都很熟:第一阶段是分发,所有节点接收到这个 Diff 之后,会拷贝老的元数据生成新的元数据;第二阶段是提交,节点接收到提交请求之后,会去对比新旧版本的元数据,一个全量对比的过程,来做变更的应用。所以最终大家看到的一个状态是,整个集群的元数据变更过程中,涉及到大量的元数据的拷贝、遍历,所以限制了 ES 集群的一个元数据扩展能力。
另外在两阶段提交的时候,它要求所有的节点响应或者是等到超时,所以这也限
制了集群的扩展能力,怎么去解决这方面的问题,我们也做了很多思考。
业界实际上对于集群的扩展性这块的话有两种典型的实现,一种典型的实现是中心化架构,类似 BigTable 和 Kudu 这种产品,它的实现是集群里面包含 Master,Master 通过分布式一致协议来保证 HA。
然后集群的整个管理的过程是通过任务的方式来进行,Master 里面会有这种异步任务去关注元数据的变化,元数据产生变化,生成任务下发给指定的数据节点去执行,这样的方式效率高扩展性好。大家可能会担心这种设计方式对中心节点 Master 的瓶颈比较高,实际上 Master 很多工作可以卸载给数据节点来完成,来降低整个 Master 的压力。
第二类典型的方案是,以 Cassandra 和 Dynamo 为代表的这种对等架构,整个集群里所有的节点对等,每个节点都保留了全量的信息,然后集群的变更是通过集群内部的元数据的同步来完成,两两节点之间互相通信,最终集群的状态达到一致。这种方案的一个好处在于,架构是比较简单清晰,但是缺点在于由于这种元数据同步的收敛比较耗时,所以通常的一个情况大家看到的是,这种方案的情况下集群的扩展能力不优。
我们基于 ES 的一个实现的方案是这样,因为 ES 本身是一个偏中心化的架构了,所以我们可以去做的一个事情是:
Master 仍然通过分布式一致协议来保证 HA,然后我们利用元数据的 Diff 来替代传统中心化架构中的任务,这样的话元数据 Diff 起到这个作用。所有的元数据的变更、生成、应用这些过程都基于 Diff 来完成,大大提高了元数据的扩展能力。
其次对于元数据提交的过程,我们实际上不要求所有的节点都响应或者超时,只要求大多数,这样来提高节点的扩展能力。所以通过这样的一个方案,我们既实现了中心化架构中,这种可扩展性强、效率高,同时兼容了开源 ES 的这些东西。
但是这种实现里面有几个注意点,一个注意点在于怎么去实现元数据多版本,我们实现的方案是 Copy On Right 的模式;第二个注意点是在于,既然你没有去等待所有节点的提交,那么元数据的路由信息需要去控制;第三个是元数据整体的损坏的预案。