• 翻译:@AdolphLWQ
  • 项目地址
  • 用时: 10h

本文介绍Uber存储平台团队是如何管理自己的存储基础设施的。他们把基础设施抽象成图模型,以此收集状态,然后根据这些信息执行运维任务、制定决策。

易于获取当前系统状态对于规模化构建、维护基础设施至关重要。由于Uber的商业持续扩张,我们的基础设施在规模和复杂性上不断增加,使得我们必要时获取所需信息变得很困难。

为了解决这个问题,我们开发了Grail,一个聚合状态信息并在一个全局视图中展示、横跨多个数据中心和区域的平台。有了Grail,我们可以更容易地开发快速、健壮的运维工具。

继续阅读以了解Grail如何通过图模型,根本性地改变Uber工程部门操作存储的方式,使团队更容易缝合不同源头的数据。

设计简单的管理方式

2016年末,为了支撑不断增加的负载,我们把所有数据库主机从旋转式硬盘更新到固态硬盘。有一步很重要,就是依然能够鉴别和追踪使用旧硬件的成千上万数据库。

那时候我们没有容易的方式获取设备的当前状态,并且还要追踪大量脚本和任务。这驱使我们寻找不同的方法来开发大规模运维工具,需求如下:

  1. 持续收集整个基础设施的状态。
  2. 唯一的全局视图。
  3. 低延迟从所有数据源获取所有数据。
  4. 关联所有数据源的数据。
  5. 简单添加和删除数据源。

Grail简介

不像Metricbeat和osquery等类似信息收集系统,Grail不收集特定领域的信息,它的角色是一个平台,以高可用和响应式的方式聚合、链接和查询来自不同数据源的数据,例如主机、数据库、部署和所有权等信息。它高效隐藏了实现细节。

此外,你可以接近实时的方式,快速获取下面问题的答案:

  1. 哪些主机当前空闲空间超过4TB?
  2. 某个团队的数据库使用多少磁盘空间?
  3. 哪些数据库运行在旋转磁盘上?

如果你的服务和主机很少,这些问题就不重要。你只需要写一个脚本,在需要的时候直接收集信息就行了。但是以Uber的规模,当你有一堆服务和数十万主机时,这种方法就失效了。节点太多响应就会慢,查询完后数据关联会出错,结果也不能反映真实情况了。大规模场景下很难及时收集状态。

一个关键结论是“不存在唯一的真理来源”。数据中心和系统的信息总是分布在多个地方,只有把它们关联起来才能做决策。更复杂的是这些状态一直在变:主机的空闲磁盘空间在变、供应新的存储集群、并行发生的其它事件。整个系统的状态不可能实时获取,只能接近它。

规模化维护

Uber的存储平台团队开发维护的存储系统支撑了拍字节的关键任务数据,我们的运维工具有一套标准的自我修复范式,有三个简单步骤:首先我们收集系统状态,然后和正常状态比较,最后处理异常数据。

如前文所述,在大规模场景下,不使用Grail这样的聚合平台是很难收集状态。举个例子,当我们想获取所有运行主机当前状态时,比如trips数据。首先我们要先找出哪些主机包含这个数据。接下来我们要连接到这些主机并收集当前状态。最后转换并展示结果。

有了Grail,我们只需要运行一条查询语句,就可以获得需要的信息:

TRAVERSE datastore:trips (SCAN cluster (SCAN db (SCAN host (FIELD HostInfo)))
)

结果以json文档的形式返回,与查询结构非常相似,对代码友好。下面的代码片段展示了运行上面查询语句的精简版结果:

{"__id": "datastore:trips","cluster": [{"__id": "cluster-trips-us1-44","db": [{"__id": "cluster-trips-us1-44-db26","host": [{"__id": "host:database862-sic1","HostInfo": {"cpuCount": 24,"puppetRole": "database","memory": {"freeBytes": 1323212425,"totalBytes": 137438953472},"disk": {"freeBytes": 48289601723,"totalBytes": 1598689906787}}}]}]}]
}

拼接数据

Grail围绕对Uber基础设施的两项观察进行设计。第一,基础设施中节点和节点间的联系可以很自然地建模为图。

模型图中的节点通过唯一的键进行标识,键由类型和名字以type:name的形式构成。数据源使用节点键将包括属性和连接的数据附加到节点上,因此数据就好像被节点键标识一样。节点的键空间是全局的,而属性和连接的键空间相对于节点是局部的。

Grail的对象模型是这样的,建模图中的节点由数据源生成的属性和连接隐式定义,这意味着下面条件至少满足一条节点A存在:

  1. 数据源产生的数据有A的属性。
  2. 数据源将节点A与至少一个其它节点关联。
  3. 数据源至少将其它一个节点与A关联。

第二点是单个基础设施概念,比如主机或数据库的信息是去中心化的。这意味着获取完整数据视图需要结合不同系统的信息。

Grail的方法是让每个数据源提供自己所属子图来解决去中心化问题。这些子图可能会有重叠,因为数据源可能把属性和连接附加到同一个节点。

上图最上面展示了三个子图。实线和颜色表示子图由哪些数据源提供,虚线表示整个图。下面的图表示从Grail用户的角度看到的视图。

通过方法,我们可以自动更新数据源的所有数据。对不同数据源,我们能够以不同的速度并行更新数据。

上图中,数据源1在键HostInfo下附加属性,数据源2键ServiceInfo下附加属性,并将此节点和关联类型Service下的一系列服务建立联系。

数据导航

随着设计的实施,我们需要一种简单的方法,能够在图中执行特定遍历。我们调研的技术中没有能很好符合需求的。比如,GraphQL需要定义模式,且不支持映射和节点间命名关联。Gremlin似乎可以,但实现并单独使用它非常复杂。所以我们开发了自己的方案。

我们的查询语言YQL,用户只需要指定一个开始节点集,然后通过后面的条件遍历图,同时与沿图属性中的字段交互。举个例子,下面的查询语句列出了所有满足条件的主机:空闲内存大于40G、剩余磁盘空间大于100G且是SSD:

TRAVERSE host:* (FIELD HostInfoWHERE HostInfo.disk.media = “SSD“WHERE HostInfo.disk.free > (100*1024^3)WHERE HostInfo.memory.free > (40*1024^3)
)

迁移到内存

从发布起Grail的架构经历多次迭代。起初,它是我们之前数据库运维工具的内部组件。第一版迭代受TAO启发,基于Python开发,使用redis存储图。当它变得低效时,我们决定把它作为一个单独服务用Go重写,使用共享的ElasticSearch集群存储。但是随着时间的推移,我们发现这个方案在快速、有效摄取和查询所需信息时,缺少伸缩性和低延迟。

我们重新思考它的架构,把之前存到共享ElasticSearch集群中的数据迁移,改为直接存储到每个查询节点上定制的内存数据库里。

当前Grail的高层架构包含三个组件:

  1. Ingesters,从配置的数据源收集数据。
  2. Coordination,确保严格的数据更新顺序。
  3. Query Nodes,为数据获取提供水平扩展能力

Ingesters周期性从预配置的数据源中收集数据,然后通过Coordination集群传输,最后存储到每一个查询节点上的datastore中。Coordination由定制的内存Raft集群实现,基于etcd Raft库开发。Raft协议确保数据更新和被存储到datastore的顺序,同时确保重启后数据一致。Coordination NodesQuery Nodes都包含了存储在datastore中的每个数据源最新数据更新。当Raft-logs被截断时,Coordination Nodes只使用datastore中的数据来创建当前数据的快照。

datastore是一个简单的键/值抽象,数据源的名字作为键,不同的键下面存储每个数据源最新的数据更新。所有数据源的数据分开存储,只有在执行查询时才聚合起来。

Grail通过在每个区域运行各自的实例,为我们提供基础设施的全局视图。每个实例负责从本地主机和服务收集数据。查询节点根据配置追踪本地和远程区域上的raft-log。当执行查询时,查询引擎把本地和远程信息结合起来。

为了扩展Grail,我们可以部署多个coordination集群、扩展查询引擎来支撑分布式查询,以便将来可以增加数据吞吐量和大小。

处理精确问题

在与分布式系统交互时,考虑到信息不准确非常重要。不管数据如何提供,来自聚合平台或直接来自源头,在系统变化时不可避免会有延迟。分布式系统不是事务的,你不能用一致的快照获取它。不管基础设施规模如何,这些条件都是对的。

我们的运维工具使用Grail的信息做决策。当这些决策需要改变系统时,在应用改变之前,我们总是确保双重检查源头的信息。举个例子,当主机端的代理程序被分配任务时,代理程序在执行任务前会先检查先决条件是否满足,比如判断主机是否有足够的磁盘空间。

关键点

正如前面所讨论的,高效基础设施管理需要深刻洞察系统状态。当规模很小时这很简单,你只需要按需查询数据即可。但是这个方法不适用大规模系统,这时你要将信息聚合到一处。正如我们在实践中学到的,当有数十万主机和许多系统时,快速获取合理且最新的系统状态很重要。

最后Grail的优势可以总结为三点:

  1. 所有数据都被聚合到支持通用查询API的单一共享模型。
  2. 低延迟查询所有地区当前状态。
  3. 团队可以附加自己特定领域的概念,并将它们与来自其它领域的相关概念关联起来。

目前,Grail服务我们存储方案的大多运维工具,并且对基础设施的各个方面都有几乎无数的使用案例。事实上随着信息范围不断增加,会有更多的使用案例。


公众号[QuanTalk],专注于计算机科学与技术、独立思考、阅读分享,开发者认知、学习、成长平台。

Grail:Uber是如何管理大规模基础设施的相关推荐

  1. Uber是如何管理大规模数据工作流的?

    让这些数据可操作,需要进行数据提取.转换.解析和编排,从而在传统商业智能.机器学习.模型训练.可视化和报表等场景中广泛应用.尽管在Uber迅速发展的初期,上线了广覆盖面的数据工作流系统,用户须针对每种 ...

  2. 用Uber的方式管理机器学习模型

    https://www.toutiao.com/a6707115213491012110/ 2019-06-27 15:52:32 Uber公司是目前对数据依赖性最高的组织之一. 每一天,Uber公司 ...

  3. 托管式服务网格:多种类型计算服务统一管理的基础设施

    王夕宁 读完需要 8 分钟 速读仅需 3 分钟 作者简介:王夕宁 阿里云高级技术专家,阿里云服务网格产品ASM及Istio on Kubernetes技术负责人,专注于Kubernetes.云原生.服 ...

  4. 有效可靠地管理大规模 Kubernetes 集群

    作者 | 蚂蚁金服高级技术工程师 沧漠 前言 Kubernetes 以其超前的设计理念和优秀的技术架构,在容器编排领域拔得头筹.越来越多的公司开始在生产环境部署实践 Kubernetes,在阿里巴巴和 ...

  5. 管理大规模容器集群能力包括_阿里巴巴大规模神龙裸金属 Kubernetes 集群运维实践...

    导读:值得阿里巴巴技术人骄傲的是 2019 年阿里巴巴 双11 核心系统 100% 以云原生的方式上云,完美支撑了 54.4w 峰值流量以及 2684 亿的成交量.背后承载海量交易的计算力就是来源于容 ...

  6. 【如何选择云主机】云主机比较与测评

    当云计算到来,IDC行业的服务商和用户也发酵着一些变化,一些喜欢拥抱新兴事物的用户已经开始使用IaaS服务,例如云主机. 本文介绍了云主机与传统IDC服务,并对云主机行业的几个主要厂家做了对比,包括盛 ...

  7. Presto on Apache Kafka 在 Uber 的大规模应用

    本文最初发布于 Uber 官方博客,InfoQ 经授权翻译如下 Uber 的目的就是要让全世界变得更好,而大数据是一个非常重要的部分.Presto 和 Apache Kafka 在 Uber 的大数据 ...

  8. Apache Hadoop 基础设施容器化在 Uber 的实践

    大数据厂长备注:以下的我们均代表 Uber 的 Hadoop 运维团队. 介绍 随着 Uber 业务的增长,Uber 公司在 5 年内将 Apache Hadoop(本文简称为"Hadoop ...

  9. 阿里云上万个 Kubernetes 集群大规模管理实践

    点击下载<不一样的 双11 技术:阿里巴巴经济体云原生实践> 本文节选自<不一样的 双11 技术:阿里巴巴经济体云原生实践>一书,点击上方图片即可下载! 作者 | 汤志敏,阿里 ...

最新文章

  1. 生成验证码点击可刷新
  2. 不是python中用于开发用户界面的第三方库-Python计算生态习题(50题)
  3. pycharm调出参数提示气泡
  4. Oracle的JDBC Url的几种方式
  5. 为什么很多技术都觉得前端很简单?为什么?为什么?
  6. Flutter进阶—质感设计之模态底部面板
  7. 活动合作 | AI NEXTCon 硅谷AI技术峰会(北京分会)大咖来袭
  8. php和python-php与python谁更适合web开发?为什么?
  9. Vue指令之v-html
  10. BottomBar之Android底部菜单
  11. vbs计算机重启代码,vbs关机代码怎么使用
  12. Centos7+搜狗拼音输入法 安装不踩雷
  13. url 转码 java_HttpClient请求URL字符集转码问题解决方法
  14. java读取目录下所有txt_java读取同目录下的txt文件
  15. 在App Store和Google Play上推广应用程序
  16. String常用方法!
  17. 使用Numpy创建数组_总结
  18. 一阶二阶数字滤波器笔记
  19. 迅为RK3588开发板Linux安卓12瑞芯微ARM核心板人工智能工业AI主板
  20. golang标示废弃方法api

热门文章

  1. 企业微信搭建私域流量增长运营双管齐下
  2. 删除所有用户数据!永久关闭
  3. CentOS版本的Linux的安装
  4. 浅拷贝之copyProperties()
  5. Java 爬取微信公众号文章(文字 + 图片)
  6. HADOOP与HDFS数据压缩格式
  7. comsol动网格(als)帮助文档翻译
  8. 关于Jason封装数据使其在前端展示的简单操作
  9. 【HTML】HTML5给网页音频带来的变化
  10. Linux下使用Curl调用Java的WebService接口