微信分享|如何在云中构建大规模分布式系统

本次分享 William 将从技术角度分析在云计算环境中,当用户业务面对流量激增、数据量翻番、访问量指数级攀升的“烦恼”时,如何利用云计算平台的弹性,结合业务自身特色,设计和构建一个高可用、高伸缩性的后端系统架构。同时会以 QingCloud 平台上的真实案例为背景,讲述从简单后端系统到大规模分布式系统的演进之路。node

讲师介绍

青云QingCloud 系统研发工程师,负责 QingStor 对象存储服务的设计与研发,对 Linux 操做系统、计算机网络、分布式系统、云计算等领域有较深刻的研究。原街旁团队创始成员,基础架构负责人。九零前,文青程序员,代码诗人,北京土著。nginx


你们好,我是 QingCloud 系统工程师王煜,今天由来分享在云计算平台上构建稳定可靠的分布式系统架构。程序员

不少企业和开发者在开发一款产品时,首要考虑的是产品功能的实现,其后端架构一般都是很是简单直接的。产品在刚上线初期,因为用户访问压力很小,数据量积累也并不大,在短期内都会运行良好。redis

然而现在移动互联网的普及和成熟,让一款产品极可能在短期内汇集大量用户,面对流量激增、数据量翻番、访问量指数级攀升等诸多“烦恼”,这原本是一件好事,但是若是后端系统不能及时扩展,势必会形成响应缓慢,频繁出错甚至拒绝服务的状况。算法

即使没有上述系统压力忽然增大的“烦恼”,产品在不断开发升级的过程当中,各类功能模块会变的愈来愈复杂,若是不能很好的梳理和组织后端架构,系统出错崩溃、不可以使用的风险也会愈来愈大。数据库

在没有云计算的时代,物理硬件从采购、上架、插线,到安装、调试、部署,再到真正投入使用,是一个漫长而耗费人力的过程,每每跟不上系统紧急扩容的节奏。而云服务的出现不只仅让咱们节约了使用成本,更重要的是能够利用云计算极度弹性的特色,让企业和开发者根据需求,对系统进行在线快速的扩容。后端

但仅仅在云服务上快速扩容是不够的,企业也须要在业务层面,关注各个系统组件的可用性和伸缩性。接下来我来给你们介绍若是利用云计算的优点,结合企业的业务特色构建稳定可靠的分布式系统。缓存

首先咱们从一个最简单的后端架构开始:安全

接入层:nginx
业务层:Java application
数据层:MySQL服务器

在云计算环境中,网络架构的组织很是重要,QingCloud 提供了基础网络和 VPC 两种网络,他们的区别在官网用户指南和之前的文章中已经介绍,这里不赘述。推荐企业使用 VPC 来构建本身的网络,将全部主机和系统资源放置在 VPC 网络中,指定内网网段(如 192.168.x.x / 172.16.x.x),主机能够经过内网地址进行通讯,该地址不会变化。

随着主机愈来愈多,IP 地址不易记忆,为了方便主机间相互识别,能够给每台主机设置内网别名。为方便在控制台管理,给每一个资源打上标签,按照标签来组织分类。

接下来咱们回到上面那个简单的后端架构。随着访问压力愈来愈大,单台 nginx + Java application 可能不足以应付,你会看到这台主机的 CPU 愈来愈忙 ,内存使用愈来愈多。并且这台主机一旦故障,整个服务都不可用了。

因此咱们首先调整这里的结构,增长多台 nignx + Java application 同时提供服务,在接入层引入负载均衡器(下文用 LB 这个词代替),使外网请求首先发到 LB 上。LB 的选择有不少,好比提供七层负载能力的 nginx 和 HAProxy,也有提供四层负载能力的 LVS,安装和配置的方法各有不一样。

LB 的引入能够分摊请求压力到后端的多台业务服务器,而且可经过心跳检查,自动隔离后端出现故障的服务器,实现业务层的高可用。但这时 LB 自己也会成为一个单点,当出现故障也会致使全局不可用。因此可使用 Keeplived 服务为 LB 提供一个副本,在一台出问题的时候能够立刻顶上,部署方法网上有不少资料。

有人会说能够经过 DNS 轮询到不一样的 IP ,实现 LB 的高可用,但事实上这样不行,由于一旦一台 LB 挂掉,DNS 还会解析到这个 LB,此时即使立刻修改 DNS,在 DNS 缓存更新以前(一般要好久),服务也是不可用的。

虽然 LB 的原理并不复杂,可是部署配置有不少工做量,并且为了实现 LB 的高可用还要额外作一些事情。QingCloud 从北京3区开始提供了高性能、高可用的 LB 集群服务,能够直接拿来使用。

改造后的架构以下图所示:

接下来咱们来思考业务层的扩展问题。首先要解决如何快速扩充业务服务器。若是业务服务器的运行环境和程序不会频繁更新,能够基于已有的业务服务器制做主机映像,当须要扩容时,直接基于映像建立新的主机,挂接到 LB 后端就能够立刻对外服务了。

此时你还可使用 AutoScaling 功能自动化这一过程,即当到达某种触发条件,如 LB 并发数、响应延迟达到多少后,自动触发主机的扩容。当触发条件不知足时,能够回收资源。

固然若是你的业务服务器的环境或程序须要频繁更新,不适合作成固定模版。此时能够本身搭建自动化部署(如 Puppet / Ansible)实现业务自动扩容,这一切操做可使用 QingCloud 的开放 API 接口,结合你的自动化部署程序完成。

此外你还须要保证业务服务器是无状态的,由于每次 LB 请求的后端可能不一样,不能假设上一次请求和这一次请求落在同一台业务服务器上。若是服务器须要保存用户访问的 session 信息,可将其下放到缓存或数据库中存储。

随着产品功能愈来愈丰富,你会发现原有单一的业务项目愈来愈庞大,各类功能逻辑交织在一块儿,当一个功能出现故障,能够引起全局不可用。此时你须要考虑将单一的业务项目分拆成多个独立子服务。子服务之间能够基于消息的通讯,亦或基于 RPC 的通讯方式。

子服务的调用可分为需同步处理和可异步处理两类。你应该尽可能异步化全部不须要立刻返回结果的请求。对于可异步处理的请求,咱们经过引入消息队列,为请求产生的数据作缓冲,请求的接收者(队列消费者)可根据队列中任务的数量作水平扩容。消息队列的选择有不少,例如 Redis, RabbitMQ, ActiveMQ, Kafka,QingCloud 平台上目前已经提供分布式、可分区、多副本的消息队列服务,具备高吞吐量、低延迟等特色,用户能够方便的集成到本身的系统中。

现在数据分析对于企业愈来愈相当重要,业务服务器在处理请求的过程当中,能够将原始数据经过队列,源源不断地导入大数据处理系统,QingCloud 提供完善的大数据分布式处理平台 Spark 和 Hadoop,用户能够根据需求方便的建立,使用和扩容。

经过拆分子服务,使得咱们有能力在某项子服务发生故障时,尽量下降对于全局的影响,提升系统总体的可用性。另外,对于处理压力比较大的子服务,咱们还能够进行独立的水平扩容,方式和前面讲到的业务服务器扩容类似,QingCloud 内网 LB 服务也能够在这里发挥做用。

改造后的架构以下图所示:

随着业务的增加,数据层面临的压力会愈来愈大,单机数据库已经不足以支撑,接下来咱们谈一下数据层的分布式和扩展技术。

对于大多数的业务场景来讲,数据的操做都是读多写少,并且读都集中在少部分的热点数据上,首先应该引入缓存层来缓解数据库的读压力,若是缓存容量需求比较大,能够构建缓存集群,在上层按照 consistent hashing 算法将数据分散到多个节点,后续须要增长新缓存节点时,只有少部分的数据会失效。

接着引入新的数据库种类,Redis 已经成为诸多企业的首选标配,由于其支持丰富的数据类型和数据查询接口,且内存型的数据库自然具备更高的性能。
你能够讲业务中关系性要求不高的数据,从 MySQL 转移到 Redis 中,尤为是列表类的数据以及计数统计类的数据。给 MySQL 减负的同时提升数据的查询性能。
单台 Redis 节点也许不能知足你对容量的需求,QingCloud 平台提供了支持多主多从 Redis 3.0 集群服务,一方面可对数据自动分区提升存储容量,另外一方面保证了服务的高可用性。

对于 MySQL 的扩展能够分为几个步骤来作。首先,增长 MySQL slave 节点,在上层将部分读请求分发到 slave 节点上去,因为 slave 同步可能有延时,业务应该能容忍短暂的数据不一致现象,举例,好比你的一个用户修改了年龄属性,其余用户要等一下子才能看到他的新年龄。

QingCloud MySQL 数据库支持一主多从的架构,而且已经在多个从节点之上作好了负载均衡,你能够轻易在界面上操做增长新的从节点来为你分担读压力。

即使有 slave 做为数据副本,你也应该按期对你的数据库进行冷备份,方便当业务出现误操做时,可以回滚或恢复到曾经的某个时间点。在 QingCloud 平台上,备份的过程能够手动执行或者配置为自动任务,在备份过程当中对数据库正常使用没有影响。

随着数据的增加,单个数据库不能承载完整的数据集合,而且写操做对于单库的压力愈来愈明显,你应该考虑分库分表技术。将比较庞大的数据表拆分出来单独存放,能够给主数据库腾出来一部分空间,分担读写压力。拆分的时候,还能够按照功能逻辑,把相关联的数据表存在一个库里。

当数据库单表很是庞大,对读写都形成瓶颈时,你须要开始考虑水平分表 sharding,这种扩展方式能够同时解决单表容量过大,读压力和写压力很大的问题,但带来的研发和运维难度也会增大,推荐把上述的优化作完之后,最后在有必要的状况下再作。

这里简略说一下水平分表的要点。首先要从数据表的字段中,选择一个合理的分区键(shard key),这个键应该是全部该表查询条件里,最常常用到的字段,这样才会使大部分的查询,可以提早判断应该向哪些特定的分区(shard)发送请求,若是查询条件中不带shard key,须要遍历全部的分区,并将结果进行merge。

有了 shard key 还要设计一种分区算法,好比常见的有按照区间,如 user_id in [0, 100] 在 shard 1,user_id in [101, 200] 在 shard2,还好比按照 hash 取模等等。设计分区算法的时候要充分考虑业务特色,多从读写操做的角度思考,这么设计可否将压力和数据均匀分摊到每一个 shard 上去。

还须要考虑数据层的扩展如何对上层透明,好比引入分布式数据库中间件,或者结合业务逻辑把数据库操做作成一个独立的子服务,供其它服务调用。若是不作成子服务,至少在业务代码里有独立的一层来封装对数据库的操做。

至此,数据层的扩展现意图以下所示:

除了上述的结构化数据的存取之外,企业还有存储海量小文件数据(非结构化数据)的需求,单机硬盘、LVM 和 NAS 能够做为临时方案使用,但都没法同时知足无限容量、高性能、高安全性、高可用性的多重须要。而自行搭建分布式存储系统,如 Ceph、GlusterFS、HDFS 适用场景很是有限,且运维和二次开发的成本也很是高。

在 QingCloud 平台上用户可使用 QingStor 对象存储服务来存储海量的数据文件,服务自己提供了无限容量、高扩展性、高可用性和高安全性的特性。

讲完数据层的扩展技术,最后来谈一下多机房部署和异地容灾的话题。QingCloud 从北京3区机房开始,经过自营的骨干网光纤和多路环网技术,使得当机房出现网络故障时对用户无感知,在基础设施上保障了高可用性。可是用户的业务若是可以多机房部署,能够在分摊访问负载的同时加速区域访问,好比加速中国南北方的用户或者海外用户的访问。

如上图所示,如果有三个机房,中间是 QingCloud 北京3区机房,负责主营业务。左边是 QingCloud 亚太1区机房,主要服务亚太和海外的客户。这两个机房都使用了 QingCloud 私有网络(VPC)部署,经过GRE或IPsec加密隧道在网络上的互联互通。右边是你办公室的物理机房,IT 人员能够在这个环境下进行开发和办公。

在业务上实现异地多活时,一般从易到难有三个阶段:第一,在备用机房搭建反向代理,用户请求到备用机房,请求直接被转向主机房,若是两机房有专线互联或延时很小,这样部署最为简单。第二,两个机房同时部署业务服务器和缓存,因为大部分数据请求能够从缓存中读取,不用进行跨机房访问。但当缓存失效时,依然要从主机房的数据库去查询。第三,两机房同时部署全套系统,包括接入层、业务层和数据层。数据层依靠数据库双主或主从技术进行跨机房同步。

最后总结一下今天的分享。没有一个所谓经典或完美的架构,只有最适合企业业务的架构,今天分享的是在最通用的业务场景下,系统在接入层、业务层和数据层的经常使用扩展方法。企业后端架构的演进过程是一个漫长而艰巨的过程,不可能从零开始一蹴而就,就能设计出一个万般周全的系统,但若是设计之初能更多着眼于将来,就能够为进一步优化留出了余地。

问题

一、企业客户,私有云如何建设不一样规模下的分布式系统?

企业首先要清楚当前业务的规模有多大,好比业务的种类,服务QPS,数据的种类和数据量的大小,同时清楚业务和数据的SLA 和性能预期。只有在清楚这些的状况下,才能在规划的过程当中有权衡取舍。

云计算环境下,基础资源的建立和销毁都很是迅速,要把更多关注放在业务层面的可扩展能力上,好比业务层要无状态,数据层要作好索引,作好冷热区分。不管规模大小,系统的组件不该该有单点故障和单点瓶颈。在规模较小的时候,系统能够不扩展,可是要具有可扩展的能力。

二、冷热数据管理以及数据持久化是怎么作的?

更热的数据应该被更快的访问到,决定存取速度的因素主要是距离和介质。从距离来看 本地内存 > 本地硬盘 > 远端内存 > 远端硬盘,从介质来看 SSD > SAS > SATA。冷热数据的比例通常是很是悬殊的,要将热的数据存放到更近更好的介质上。

每一种存储系统诸如 MySQL Redis 都有本身的数据持久化策略。

三、数据大集中平台的安全性是否比原来点对点接口低?

其实不管数据的存储形式是怎样的,数据的安全性主要取决因而否有冗余,冗余度是多少,冗余的分布是不是跨物理机,甚至是否跨机房。数据写入是否真正落盘,以及数据的副本是同步写入仍是异步写入。

四、构建大型分布式平台系统,缓存管理用redis来实现,应该注意什么?

首先考虑缓存的粒度,太粗的粒度会致使失效太频繁。还要考虑缓存容量,若是单台节点没法承载足够的热点数据,在使用多节点是要注意选择合适分布策略,比较常有的有一致性hash和hash取模。Redis3.0以上版本提供了集群能力,能够自动对数据分区,并提供高可用能力。

五、分布式数据库、缓存,如何实现资源池化?

可在数据库服务之上增长代理中间件,有开源方案也有本身实现,对使用者提供的接口要屏蔽分布式的细节,用户不用关心容量,性能,分布策略等,仿佛看到的是一台单机数据库

六、大规模分布式系统下后端交易数据是如何存放的,如何实现数据的多中心容灾保护?

交易数据最重要的是不能丢失,性能是次要,曾经不少传统企业会选择oracle这样的商业数据库,新型企业愈来愈多愿意采用 MySQL PostgreSQL 等开源实现,可是配置的时候必定是配成最严格的同步写多份成功才返回,而且有日志留存

七、云计算适合哪些类型的应用,衡量标准是什么?

云计算作为 IT 基础设施资源,在各行各业都有成功案例,已经不分适合哪类应用。惟一衡量标准就是可否知足需求,要看是否能取代传统硬件可以提供的能力,而且可以提供传统硬件之外的能力,例如弹性伸缩,按用量计费,快速启动销毁等。

八、keepalived的性能如何?后端是HAPROXY吗?

keepalived 主要经过引入虚拟路由冗余(VRRP)来实现高可用,本质上不会对性能形成影响,它是一个独立的服务,和HAProxy没有关系。

九、青云QingCloud 的云服务是否可以预防因为namenode掉电等缘由引起的hadoop集群崩溃?

目前青云的IaaS层在物理机掉电时会触发灾难恢复,另外一台一样的主机会启动起来,数据不会丢失,而后再启动hdfs的服务便可恢复集群使用。Hadoop的自身的HA也会很快提供,这样就能够自动恢复hdfs服务了。

十、auto scaling太多实例,db最大链接耗尽如何处理?

能够在实例和db之间引入代理中间件,还能够本身实现一个独立的数据访问服务,不让实例直接操做db。

相关文章
相关标签/搜索