更多相关文章阅读
个人简介
王亚雷
清华本科,美国德州大学奥斯汀分校硕士。十多年从事互联网服务平台,分布式计算和数据存储的开发和技术管理工作。先后任职微软总部、eBay 和 Twitter 总部。
我一直从事后台的海量分布式的数据存储系统的设计、研发及运维。早期在微软,刚开始的时候在 SQL Server;后来转到微软的 Online Service Division (OSD)。
在 OSD 研发分布式的 In-Memory 数据库,主要是支撑微软的整个数字广告系统。这个系统的要求很高;5毫秒响应时间,单机的 QPS 要达十万以上。后来去了 Twitter,主要充实 Twitter 的分布式 Key-Value 数据库的研发、运维。
一、形形色色的数据库
Twitter 整体存储架构有如下四套系统:
1、NoSql,主要包括用户信息、比较小的数字;当时大约有三万多节点。
2.、大文件系统,主要是存储图片、video 等大数据文件。与 NoSql 同样,也有三万多个节点。
3.、Hadoop 系统,主要用于后台数据处理、分析;最多的时候有九千个节点左右。
4.、MySQL,简单、比较复杂的关系性数据查询
各种数据库的 CAP
说到数据库,不得不说的就是 CAP。CAP 是什么呢?C就是一致性。A是可用性。P就是分区容错性。
Eric Brewer 证明了在 CAP 三个诉求中,你只能满足两个;永远做不到三个。所以你做数据库设计的时候就要考虑应用场景是什么;牺牲那个特性来取得另一外两个特性。
事实上所有的数据库,包括现在新兴的数据库都遵从这个 CAP 原则。它们针对某个应用场景做优化,没有一个大而统什么都能用的系统。
下面是不同类型数据库对 CAP 的抉择:
关系型数据库,主要应用于交易系统;例如银行系统。因此它是强一致性的;放弃了A。
NoSql 的好处在于它的高并发,能够支撑很高的并发数;但是一致性稍差,是最终一致的。
NewSQL, 如 google 的 spanner 号称能够同时满足 CAP 三个;实际上是采取了一些措施来增强网络的稳定性,把网络出现 partition 的可能性降低很低。但是理论上还是 不能突破 CAP。
特殊用途的数据库;例如时间序列型的 OpenTSDB,文档型的 mongoDB 以及图数据库 Neo4j 等。
二、Manhattan 的前世今生
Twitter 最早用的是 Cassandra。早期 cassandra 没有虚拟节点导致不能部分的扩容;现在的 Cassandra 已经可以了。
第二个就是 Cassandra 用的是 gossip 协议。在实际应用中,当集群变来较大时,如达到几百个节点,gossip 协议不能够有效的让分布式系统保持一致性,存在一定程度不一致的问题。
在以上问题的驱动下,twitter 研发了自己的 NoSql 也就是 manhattan 系统。manhattan 设计实现主要关注的要素如下:
可靠性;
可用性;
可操作性;
低延时;
高效;
manhattan 分布式实时海量数据库目前有三万多个节点,每个节点可以支撑上万 QPS;P99延时为10毫秒。
三、Manhattan 设计之存储引擎
首先,做一个 One Size Fit All 系统是肯定不可能的。所以我们当时特意做了模块化设计;后面的存储结点和存储引擎是可以接插的,可以根据不同的需求来定制数据系统。
因此,我们的后台有下面三类常见数据引擎和一些专门用途的引擎。
常见数据引擎
SeaDB 是只读优化。因为我们有很多用户;尤其是广告客户,他们是定期往上面更新数据的。这个时候很适合做批量更新,但是前端是只读的。
SSTable 针对写优化的存储引擎。与 google 的 bigtable 机制是类似的,它对写是非常高效的。
RMDBS 传统的关系数据库系统。有很多用户是同时读写的,同时对读是很在意的。此时 RMDBS 是可以进行 index 又可以实时的 update。
专门用途的引擎主要是从以下三个方面进行优化的措施:
强一致性;
时间序列服务;
二级索引;
四、Manhattan 设计之架构
Manhattan 整体架构分为四部分;分别是调度、读、写以及一致性协调。
Cordinator 调度模块,它的主要功能是对请求打包,然后根据不同 key 将其分散到不同的后台节点上;最终将节点的响应重新组装返回给请求方。
这些不是在 Coordinator 调度模块里面,是在后端存储模块里面。bloom filter 可以快速排除分布式的表里面不存在某个值。从而极大地提高查询效率。
读请求,对于 SSTable 这种架构的存储;读的代价时非常高的。因为它要读很多很多 SSTable。
当然我们有很多措施可以对其进行优化。第一就是定期将小的合并成大的 SSTable。第二我们有两级索引;一级驻内存,另外一级在磁盘中,第三是使用 Bloom filter,这样能保证我们的加速。
写过程实际上是直接写到内存里的,commitlog 是非常快的;所以写的效率很高,基本上可以看作是写到内存里的。
Reconciliation 就是最终把所有写入的数据复制;通过这种 job 对它进行传播保证它有同样的数据。
同时,reconciliation 有个定期的工作就是扫所有的文件;然后把文件的不一致进行整合达到最终一致性。
五、海量系统高效运维实战
Twitter 数据量非常大;大家都知道这个请求是有叫做放大特性的。例如前端要调用一个,后端可能有几百个调用。我们最大的集群每秒有两三千万请求,线上有十几个这样的集群;所以运维这样的系统非常痛苦。
曾经有个很极端的例子,有一个 SRE 经过一段时间煎熬,白天突然在办公室昏倒。后来我们在运维方面做了成功地改进,引入 DevOps。DevOps 实际上指的是分别从组织架构、流程、工具三个方面来提高系统运营的效率
海量运维-组织架构
大家可能知道,常见的情况是研发写了 code,结果运维出问题了。代码也不知道干什么的,半夜三更被叫起来,气得要死;然后找研发。研发说你这个都不懂还来当运维。于是无法调和的矛盾就这样产生了。
所以靠人是不行的;最有效的是组织架构,有了这个所有的问题引刃而解。为什么这么说?研发参与运维和运维全部打成一块。这时候你写个烂代码,你半夜三更被叫起来。或者你写了一个不必要的报警,你的同事被叫起来,第二天是要被臭骂一顿的。
在项目交付流程中,运维在项目早期一定要参与研发设计。研发的设计是必须要经过运维 signoff;运维不 signoff,研发的设计不能算完成。
研发在设计之中有两个比较的重要的 work items 必须要有。第一个是运维指标。
第二个就是告警,这些都是 要通过大家讨论的。服务上线交给运维之前,运维操作手册是必须要完成的,一定要有服务或者功能模块很完整的操作手册。
最后在上线之前有个预上线的会议,基本上研发线、运维线的各个部门包括安全都要了解产品或功能上线的方方面面并 sign off。
上线后,研发项目组必须自己运维自己的功能模块一个月。通过一个月的产品磨合,最后再进行培训和交割。东西要交给大家做的时候,必须要有一个面向所有研发和运维的培训流程。
海量运维-流程
所有人都需要上岗运维,但是需要一个很好的流程。首先培训,新人来了以后;老人开一到三次的讲座,介绍产品,介绍运维经验。
然后就是所谓的 Shadow Others,当资深运维在处理问题时你在他旁边看着,记录、重复他所做的所有操作活动。
下一步就是 Shadow by Others,在这个阶段,由你来处理所有的问题,有资深的运维同事做后备。所有这些都通过了,你就可以独立上岗了。
海量运维-工具
具备了正确的组织架构和有效的流程后,Devops 的第三个支柱是方便易用的运维工具。这些是以运维推动,运维和研发共同实现的工具。我们有几个工具帮助我们极大的降低了运维的成本。
Self Service,以前运维的服务80%是内部团队的;有很多内部服务我们花了很长时间在上面。所以我们设计了一个 Self Service UI,极大的降低了沟通成本。
只有10%很特殊的服务或者很重要的服务,我们会跟他们沟通处理。这里面有个很重要的功能是调试工具。因为大家服务上线了,有了调试工具的 UI 就非常方便了,高亮批注读写一个 Key-Value 非常方便。
部署,需要各种不同的环境,测试环境、生产环境等。对于数据服务来说,需要注意 canary 两个节点不能在一个 replication set 上。
部署的回滚能力特别重要。凡是不涉及到任何数据格式变化的变动一般来说都没有什么大问题。但是,一旦涉及到数据尤其是数据的格式的改动就要非常小心;数据格式变动后就没有办法回滚了。
所以部署一定是分两步的。第一步,先把新的代码部署上去,新的格式不要变;新的代码能够同时处理新旧数据格式。第二部,升级一下,新的数据格式就进来了,这样就不怕了。
Topology Transition,当需要在线的扩容或着嫁接节点的时候;我们需要有个所谓的状态驱动来保证数据的一致性和统一性不受影响。
当时老的方法痛苦在于这是一个 all or none 的过程,一个迁移过程如果失败了,即使已经完成了90%,也还是必须重来,这个对于 SRE 来说是非常痛苦的。
我们后来设计了一个渐进式的迁移方法,能够记住当前状态。这样可以随时从当前的状态重新恢复。
六、运维的挑战与机遇
尽管 Twitter 在运维方面做了很多工作,但是还是有很多问题和需要改进的地方。例如,故障排除高度手工化。
因为 twitter 所有的服务的指标种类加起来总共超过10亿。一旦出问题,排查起来就是一件很痛苦的事情。
对于这么多指标,哪些有问题、哪些没问题;人是很难判断的。但是机器可以通过对比历史数据并分析是可以做到异常自动发现的。
大家可能有经验,前端出问题往往是由于后端导致的。怎么将前后端关联起来,这个机器是完全可以快速完成的;这样一来就可以节省很多人工的时间。
很多时候知道到服务指标不正常可能还不够,这时需要查看日志。查看日志难度大,日志信息多,噪声大,找到需要的信息不容易,而且还需要关联时间;为此我们做了日志分析和整合的系统。下图是日志的整合、聚类对比的结果。
智能运维案例分析
这是一个央企大客户,他们业务上传经常出现阻塞;这个点是机器自动标识出来的。通过机器标识可以建立很灵活的报警规则。
另外一个客户 CPU 突然飙高,不知道什么原因;通过智能关联排查故障根源工具发现这个是一个 hbase 写也增加了。把这些有用的信息推荐给客户,客户很快知道了是由于一个配置修改造成的问题。
这是另外一个客户,非常重要的门户服务器经常出现飙高;但却一直不知道什么原因。后来通过我们的工具自动找出了问题;我们找道了问题进程和详尽信息,详尽到包括用什么语言写的。
后来发现是他们的 SRE 写的一个脚本,后来没有用了,但扔在那儿忘了;结果每天都在跑,浪费计算资源。导致他们服务受影响。
我们做这套东西对故障诊断有非常大的帮助。这也是我们建立这个智能管理整个一站式解决方案的原因。
最后一个智能知识库是把大家的运维知识不断积累放在里面;同时机器能够自动学习,就像一个一个机器大脑,随时可以查询,相当于一个运维的知乎。