阿里巴巴代码平台架构的演进之路

简介: 这事儿和伽利略有关。

代码平台的发展之路

相信很多做后端服务的同学在看到单机、读写分离、分片这些字眼一定不会觉得陌生。没错,代码服务在发展的开始阶段面临的问题和其他web服务大体一致,所以使用的解决方案也大体一致。

DM_20210813150206_001.PNG

单机服务

众所周知,Git是一种分布式的版本控制软件,每个人的本地都有一份完整的代码版本数据。但为了解决多人协同开发和流程管控(评审、测试卡点等),需要一个集中式的远端中央仓库来完成这些功能,这就是单机服务的来源。

读写分离

随着协同人数的增多,以及提交数量的变多,单机升配也无法解决调用量过高的问题。而通过统计我们发现,对于Git服务读写比例大概是20:1,为了保证主链路提交的正常,我们做了读写分离,来分散压力。通过主备同步来完成数据的同步,并使用一写多读的架构来扩展读服务的能力。

分片

但无论如何做读写分离,所有机器的规格始终是一样的。虽然仓库数量的增加、平台用户的增加,无论是存储还是计算都会达到单机所能承载的极限。这个时候我们采用了分片的方式,即将不同的仓库划分到不同的片中,而每个片都是一个完整的读写分离架构。当一个请求到来时,服务会根据查询库特征信息,决定这个仓库所在的分片,而后又根据接口的读写特性,将请求转发到具体的机器上。有点类似于数据库中的分库分表。这样以来,通过分片+读写分离的架构,我们理论上可以支持水平上的无限扩容。


问题及思考

那么分片+读写分离是否是解决代码服务大规模、高并发问题的银弹呢?在我们看来,答案是否定的。
伴随着代码服务体量的发展,我们解决的核心问题一直以来主要是两个:

  • 集中式的Git存储服务,既是I/O密集型也是计算密集型(Git的压缩算法);
  • 文件数量众多,单个仓库的文件数量也可能是十万甚至百万级,对数据一致性的保证和运维可靠性的挑战极大。


实际上,代码平台架构的发展,就是在这两个问题之间找平衡,以在一定规模情况下保证整个平台的稳定性。但一直没有根本性地解决掉这两个问题。然而随着规模逐步上涨,上述的两个核心问题引发的劣势又逐步变得明显起来。


代码服务主备架构:有状态服务带来的问题


对高可用系统比较熟悉的同学,从名字上应该就看出些许端倪。主备架构的读写分离方案其天然引入的就是有状态服务的问题。

DM_20210813150206_002.PNG


整个系统的请求流转,主要分两次转发:

  • 通过统一的代理层,可将用户的不同客户端请求转发到对应的系统上,如Git命令行客户端的SSH协议和HTTP协议、页面的访问及API接口请求等。
  • 然后对接的模块会将用户不同协议的请求转换为内部的RPC调用,并通过统一的RPC代理模块RPC Proxy和分片服务Shard Config将请求按分片和读写转发到对应的服务上。


读和写操作如何处理

如果是一个写操作(如:push,从页面上对文件、分支等进行新增、删除、修改等操作),请求则会落到仓库对应分片的RW/WO服务器上,在RW/WO服务写入完成以后,再通过Git协议的同步方式,同步到同分片的其他机器上,这样一次写操作就完成了。而对于读操作,则是在仓库对应分片中随机找一个RO的机器进行转发。

问题分析

当某个分片的主节点发生异常(服务crash或服务器宕机等),分片内的机器状态会发生变化。原本的RW/WO状态会置为不可用,Backup的机器会取代原来的RW/WO服务来承接写操作的请求。

从系统的角度上分析,主备架构存在以下四个问题:


1、可用性:

  • 由于读写操作是分离的,所以在写服务器failover期间,服务的写功能是无法使用的;
  • 对于单片而言,写操作是单点的,一台服务波动则整个分片都波动。

2、性能:

  • 主备机器在同步上需要额外的时间开销。对于松散文件、文件压缩的Git仓库,这个耗时比单文件拷贝耗时更久。

3、安全:

  • 用户侧的短时间内的瞬时操作,对于节点同步来说可能是并发的,无法保证同步中的事务顺序。

4、成本:

  • 同分片写,主备机器要求规格完全一致。但由于接收的请求不同,存在严重的资源消耗不均;
  • 由于同步的小文件多,对延时敏感,跨机房异步同步,机器规格一比一复制。


这四个系统上缺陷带来的问题,在一定使用规模和服务稳定性要求下是可以容忍的。但随着商业化的深入和用户规模的增长,这些问题的解决变得迫在眉睫。接下来我将和大家分享在过去的一年中,我们团队对这些架构上问题的思考和解决思路。


代码服务多副本架构:消灭有状态的存储服务

在上一个小节中,我们已经比较清晰地认识到架构上面临的四个问题主要是有状态服务带来的。那么在新架构的设计中,我们的目标只有一个——消灭有状态的服务。目标有了,如何去实现?我们首先对业内几个流行的分布式系统做了深入的了解和学习,比如ETCD、Paxos协议的学习等。同时我们也学习了代码服务的老大哥——Github开源的寥寥文章,但Github认为分布式架构是他们的核心竞争力,所以可参考的文章较少,但从这些文章中我们依然深受启发。首先对于任何架构升级,要能做到“开着飞机换引擎”,让架构软着陆是架构升级的保底要求。因此在grpc的代理层之上没有任何的改动。从内部的RPC调用以下则是我们新架构实施的地方。

和前一节的不同,在新的底层设计中:

  • 我们希望设计一个GPRC D-PROXY的模块,能将gRPC的请求做到写时复制,从而达到多写的第一步;
  • 其次在Proxy Config的模块中来存放仓库、副本、机器等元数据;
  • 再次通过一个分布式的锁(D-Lock)来完成对仓库级别的锁控制;
  • 最后我们希望有一个快速的算法能计算仓库的checksum,快速识别仓库的副本是否一致。

DM_20210813150206_003.PNG

通过这些模块的组合完成仓库多副本的并发写入、随机读取,我们就可以去除底层存储节点的状态,从而能将仓库的副本离散到不同机房中。此外得益于机器与副本的解耦,每个服务器都可以有独立的配置,这也为后续的异构存储打下了基础。


代码服务多副本架构的实现

有了基础的设计,通过MVP的实现,我们验证了这个架构的可行性。并通过一年多的时间进行开发和压测,最终将我们的多副本架构成功上线并逐步开始提供服务。在实现过程中,我们为这个系统起了一个颇有意义的名字——伽利略,因为在我们的多副本架构中,最小的副本数是3,而伽利略在发明了天文望远镜观察到火星的卫星恰好就是3个。我们希望秉承这个不停探索的精神,所以起了这个有意义的名字。在具体的设计中,我们通过对gRPC proxy模块的改写,让来自用户的一次写操作完成写复制,并通过对git的改写以支持分段提交。我们基于git的数据特性,编写了checksum的模块,可以对git仓库进行快速的全量和增量一致性计算。

DM_20210813150206_004.PNG

伽利略架构在系统架构层面解决了之前主备架构带来的问题:


1、可用性提升:多写和随机读让底层的git存储服务不存在写单点和failover的切换问题;

2、写性能提升:副本并发多写,让底层的副本间不存在主备复制的时间开销,性能比肩单盘;

3、安全:写操作的分段提交和锁的控制,在解决分布式系统写安全的基础上也控制了用户写操作的事务性;

4、成本大幅度降低:

  • 每个副本都会承担读写操作,水位平均
  • 副本与机器解耦,释放机器的规格限制,可以根据仓库的访问热度采用不同涉及机型和存储介质


说了这么多,当用户执行push后,在伽利略中会发生什么呢?我们用一个动画来简单演示下:

DM_20210813150206_005.GIF

  1. 用户3和用户4是两个着急下班的同学,他们本地master分支分别是提交3和提交4;
  2. 底部灰色的圆圈代表的是服务端一个仓库三个副本的装填,可以看到其中两个master分支指向的是提交2,而其中有一个可能因为网络或者其他原因导致其master的指向为1;
  3. 当用户3和用户4前后提交了代码,由于用户3更快达到服务,所以会率先启动写的流程;
  4. 在一个写的流程开始,首先会对当前仓库副本的一致性进行检查,系统很容易就发现落后的副本1与其他两个副本不一致,因此会将其标记为unhealthy。对于unhealthy的副本,是不会参与伽利略写或读的任何操作;
  5. 当用户4的请求也被受理后,也会触发一致性检查,但是由于副本1已经被标记为unhealthy,所以对于用户4的流程,这个副本就“不可见”了;
  6. 在用户3的进程检查后,发现多数副本是一致,则认为是可以写入的,便会将非引用数据传输到副本中;同理用户4的进程也是一样,且因为非引用数据不会变更分支信息,所以不需要加锁,可以同时操作;
  7. 当用户3的进程收到非引用的数据传输成功后,便要开始进行引用的更新,这时第一步先去抢占这个仓库的锁。很幸运锁是空闲的,用户3的进程加锁成功,开始改写副本的引用指向;
  8. 当用户4的进程也完成了非引用数据传输后也开始进行引用的更新。同样,再更新操作前要去抢锁,但发现锁已经被占用,则用户4的进程进入等待阶段(如果等待超时,则直接告诉用户4提交失败);
  9. 当用户3的进程改写引用成功后,会释放掉仓库锁。此时服务端的仓库的master分支已经被修改为指向3。用户3可以开心下班了;
  10. 当锁被释放后,用户4的进程快速抢占,并尝试修改引用指向,但发现更改的目标引用master已经和之前不同(之前是2,现在是被用户3更改的3),此时用户4的进程会失败并释放掉锁。在用户4的本地会收到类似“远端分支已经被更新,请拉取最新提交后再推送”的类似提示。


以上就是多个用户同时提交时,伽利略系统内部发生的事情。眼力好的同学可能会问,那在系统中被判定unhealthy的副本会怎么办呢?这个就是刚才在架构实现中提到的运维系统会做的事务补偿了,运维系统在收到unhealthy上报和定时扫描后都会触发对unhealthy副本的修复,修复后的副本在确认一致后会置为healthy并继续提供服务,当然这个过程在判断修复是否一致也是加锁操作的。


代码托管运维管理平台

除了上小节提到的副本修复,在系统运行中,还需要很多的运维操作。以往这些都是由运维同学操作的。Git服务涉及数据和同步,比单纯的业务系统要运维复杂度要高,对应运维风险也比较高。在过去的一年中我们结合以往的运维经验,以及新架构的需要,以工具化、自动化、可视化为目标,为伽利略系统打造了对应的运维管理平台:

DM_20210813150206_006.PNG

通过这个平台我们大大提升了运维的质量、也充分释放了运维人员的精力。


欢迎大家使用云效云原生时代新DevOps平台,通过云原生新技术和研发新模式,大幅提升研发效率。现云效公共云基础版不限人数0元使用,羊毛不薅白不薅。欢迎点击链接前往阿里云云效官网了解:https://www.aliyun.com/product/yunxiao?channel=hy

相关文章
|
1月前
|
数据采集 机器学习/深度学习 大数据
行为检测代码(一):超详细介绍C3D架构训练+测试步骤
这篇文章详细介绍了C3D架构在行为检测领域的应用,包括训练和测试步骤,使用UCF101数据集进行演示。
44 1
行为检测代码(一):超详细介绍C3D架构训练+测试步骤
|
1月前
|
SQL 存储 分布式计算
ODPS技术架构深度剖析与实战指南——从零开始掌握阿里巴巴大数据处理平台的核心要义与应用技巧
【10月更文挑战第9天】ODPS是阿里巴巴推出的大数据处理平台,支持海量数据的存储与计算,适用于数据仓库、数据挖掘等场景。其核心组件涵盖数据存储、计算引擎、任务调度、资源管理和用户界面,确保数据处理的稳定、安全与高效。通过创建项目、上传数据、编写SQL或MapReduce程序,用户可轻松完成复杂的数据处理任务。示例展示了如何使用ODPS SQL查询每个用户的最早登录时间。
94 1
|
11天前
|
SQL 数据采集 分布式计算
【赵渝强老师】基于大数据组件的平台架构
本文介绍了大数据平台的总体架构及各层的功能。大数据平台架构分为五层:数据源层、数据采集层、大数据平台层、数据仓库层和应用层。其中,大数据平台层为核心,负责数据的存储和计算,支持离线和实时数据处理。数据仓库层则基于大数据平台构建数据模型,应用层则利用这些模型实现具体的应用场景。文中还提供了Lambda和Kappa架构的视频讲解。
【赵渝强老师】基于大数据组件的平台架构
|
17天前
|
机器学习/深度学习 人工智能 自然语言处理
医疗行业的语音识别技术解析:AI多模态能力平台的应用与架构
AI多模态能力平台通过语音识别技术,实现实时转录医患对话,自动生成结构化数据,提高医疗效率。平台具备强大的环境降噪、语音分离及自然语言处理能力,支持与医院系统无缝集成,广泛应用于门诊记录、多学科会诊和急诊场景,显著提升工作效率和数据准确性。
|
24天前
|
存储 安全 Java
系统安全架构的深度解析与实践:Java代码实现
【11月更文挑战第1天】系统安全架构是保护信息系统免受各种威胁和攻击的关键。作为系统架构师,设计一套完善的系统安全架构不仅需要对各种安全威胁有深入理解,还需要熟练掌握各种安全技术和工具。
67 10
|
1月前
|
机器学习/深度学习 网络架构 计算机视觉
目标检测笔记(一):不同模型的网络架构介绍和代码
这篇文章介绍了ShuffleNetV2网络架构及其代码实现,包括模型结构、代码细节和不同版本的模型。ShuffleNetV2是一个高效的卷积神经网络,适用于深度学习中的目标检测任务。
71 1
目标检测笔记(一):不同模型的网络架构介绍和代码
|
23天前
|
监控 API 调度
开放源代码平台Flynn的架构与实现原理
【10月更文挑战第21天】应用程序的生命周期涉及从开发到运行的复杂过程,包括源代码、构建、部署和运行阶段。
|
1月前
|
机器学习/深度学习 自然语言处理 搜索推荐
大厂 10Wqps智能客服平台,如何实现架构演进?
40岁老架构师尼恩,凭借深厚的架构功力,指导众多小伙伴成功转型大模型架构师,实现职业逆袭。尼恩的《LLM大模型学习圣经》系列PDF,从基础理论到实战应用,全面覆盖大模型技术,助力读者成为大模型领域的专家。该系列包括《从0到1吃透Transformer技术底座》《从0到1吃透大模型的基础实操》《从0到1吃透大模型的顶级架构》等,内容详实,适合不同水平的读者学习。此外,尼恩还分享了多个智能客服平台的实际案例,展示了大模型在不同场景中的应用,为读者提供了宝贵的实践经验。更多技术资料和指导,请关注尼恩的《技术自由圈》公众号。
大厂 10Wqps智能客服平台,如何实现架构演进?
|
1月前
|
消息中间件 缓存 Java
亿级流量电商平台微服务架构详解
【10月更文挑战第2天】构建一个能够处理亿级流量的电商平台微服务架构是一个庞大且复杂的任务,这通常涉及到多个微服务、数据库分库分表、缓存策略、消息队列、负载均衡、熔断降级、分布式事务等一系列高级技术和架构模式。
91 3
|
2月前
|
Cloud Native Java 编译器
将基于x86架构平台的应用迁移到阿里云倚天实例云服务器参考
随着云计算技术的不断发展,云服务商们不断推出高性能、高可用的云服务器实例,以满足企业日益增长的计算需求。阿里云推出的倚天实例,凭借其基于ARM架构的倚天710处理器,提供了卓越的计算能力和能效比,特别适用于云原生、高性能计算等场景。然而,有的用户需要将传统基于x86平台的应用迁移到倚天实例上,本文将介绍如何将基于x86架构平台的应用迁移到阿里云倚天实例的服务器上,帮助开发者和企业用户顺利完成迁移工作,享受更高效、更经济的云服务。
将基于x86架构平台的应用迁移到阿里云倚天实例云服务器参考