【AICon】 如何构建高效的 RAG 系统?RAG 技术在实际应用中遇到的挑战及应对策略?>>> 了解详情
写点什么

Monzo 是如何从 0 开始构建 7*24 小时不停歇的银行后台系统的?

  • 2016-11-29
  • 本文字数:3563 字

    阅读完需:约 12 分钟

对于银行后台系统来说,稳定性是非常重要的;而对于移动银行来说,还需要面对数以亿计的客户。Monzo 遇到的正是这种挑战,客户一方面需要 7*24 小时能够管理他们的钱,因此数据延时、单点故障等是不可接受的;另一方面又希望他们的需求能够很快实现。

正因为如此,Monzo 的后台系统从一开始就设计成分布式微服务架构。一些大型互联网公司(例如亚马逊、Netflix、Twitter 等)的实践已经证明,独立大型应用在用户数量快速增长或者开发人员数量增长之后,会导致扩容、需求响应等一系列问题。同时,Monzo 的业务发展方向,需要针对不同地区的客户进行定制化,为了提高开发效率,必须减少开发团队之间的耦合。

Monzo 后台系统开发人员最初只有 3 个人,必须从务实开始。最初的团队选择了他们相对熟悉的技术,确定了方向就开始构建产品,但是技术时刻在改变。

Monzo 开发工作室

当 Monzo beta 版本发布的时候,他们的后台服务已经有将近 100 个,同时开发团队也在快速增长。此时,他们开始考虑现有系统的架构问题,梳理出以下几个着重关心的领域:

  1. 集群管理:随着服务数量的增加,需要有个自动化的方式管理大量服务器、分布式任务和服务器故障;
  2. 多语种服务:在 Monzo 主要使用 Go 语言进行开发,但是没有一种语言的生态环境可以满足整个银行后台系统的需要,因此整个后台需要能够承载多种语言环境的服务;
  3. 远程调用框架:由于有大量离散的服务,分布在不同的主机、数据中心、甚至不同大陆,后台系统必须有一个强大的远程服务调用层,以处理模块故障,降低延迟,理清调用链路。
  4. 异步消息:为了提高后台系统的性能和可伸缩性,Monzo 通过异步消息队列将业务逻辑放入“后台”运行,消息队列必须保证极强的可靠性,以避免消息丢失的发生。

下面我们就来逐一了解这些系统的详细设计和选型。

集群管理

Monzo 系统包含大量微服务,如果一台主机上只部署一个服务,会造成对服务器的大量浪费。按照传统方式将服务器归类,会增加服务扩容的难度。因此,一个支持快速伸缩的集群调度系统,应该抽象出应用程序的运行环境,将运行环境和底层硬件进行隔离。调度算法根据应用程序负载和可用资源,对其进行扩容和缩容。另外,Monzo 在设计集群管理系统时,希望能够让所有的应用程序共享一个调度器,因此它不仅需要能够调度无状态服务,还需要能够调度有状态服务。

容器化的提出,特别是 Docker 的兴起,将前面提到的抽象层进行了标准化。首先,通过将应用程序及其运行时依赖打包成一个镜像,使得应用程序运行环境和主机解耦;然后,通过整合 Linux 内核的隔离特性( cgroup namespace ),使得主机上运行的多个服务之间能够相互隔离,减少干扰。这样,集群管理服务对应用程序可以做到黑盒,将重心放到服务编排上去。

Monzo 最初使用 Mesos + Marathon 的架构,随后切换到了运行在 CoreOS 上的 Kubernetes 。下图展示了在切换到 Kubernetes 之后,整体开销的变化:

从上图可以看见,使用 Kubernetes 之后,整体开销开始下降。这是因为所有系统都共用资源池。例如,之前 Monzo 的构建服务搭建在独立的 Jenkins 服务器上,使用了 Kubernetes 之后,构建服务由 Kubernetes 根据机器可用资源分配到现有机器上。Kubernetes 的资源分配和限制模块可以尽可能的利用机器空闲资源,并且保证低优先级的任务不会影响高优先级任务。

另外,通过在AWS 上将Kubernetes 以 HA 模式部署之后,系统稳定性有了明显的增强,Monzo 开始在 AWS 上部署类似 Netflix 的 Simian Army ,对生产环境服务进行破坏性操作,以验证生产环境对服务失败的容错能力。

多语种服务

Monzo 后台系统主要使用 Go 语言编写,因为 Go 语言在构建低延时高并发应用程序上有先天的优势。但是一种语言很难完成整个银行后台系统的搭建,因为系统中可能会用到大量不同语言编写的开源软件,同时技术人员也会有不同的语言偏重。

Docker 的出现解决了多语种应用部署的问题,它将应用程序及其运行环境一并打包,调度系统无需关注其内部使用的具体语言。但是多种编程语言的混用,会降低代码的复用程度,因为无法再抽取公共代码成为类库相互引用。

为了解决这个问题,Monzo 将大量基础服务采用 RPC 的方式暴露出来,将“代码共享”变成了“基础服务共享”。例如,如果要获取一个分布式锁,无需通过客户端访问 etcd ,而只需要通过封装好的 RPC 接口即可。通过将基础服务(例如数据库、消息队列等)RPC 化,每种新的语言只需要发起 RPC 调用,即可使用现有的基础服务。通过这种访问,Monzo 完成了对 Java、Python 和 Scala 等语言的兼容。

RPC 框架

上一节提到了,Monzo 通过 RPC 的方式将基础服务暴露出去,因此它们的基础架构需要一个强大的 RPC 框架,以支撑其微服务架构。

首先是传输协议,为了能够让多种语言构建的服务之间能够方面交互,HTTP 协议是首选的传输协议。几乎每种语言都有实现 HTTP 协议的标准库,这能够降低使用门槛。

另外,要能够支撑整个微服务架构,RPC 框架还应该有以下这些特性:

  • 负载均衡:大部分 HTTP 库都实现了基于 DNS 的轮询负载均衡,但是这个方式比较生硬。理想的负载均衡应该能够选择最合适的目标服务器,以达到较低的失败率,较小的延时。这样即使集群中出现因为故障而进行复制的副本,也不会影响整个系统的性能。
  • 自动重试:对于分布式系统来说,故障是难以避免的。如果一个幂等调用失败,RPC 系统应该要能够自动请求集群中的其他副本,以确保集群中存在少量故障节点时,系统整体仍然可用。
  • 连接池:如果每个请求都需要重新创建连接,远程调用的延迟会大大增加。理想情况下每个远程调用请求都应该尽可能复用之前已经创建的连接。
  • 路由:对于一个 RPC 系统来说,能够运行时修改目标机器是非常有必要的。例如一个新版本服务上线,可能需要一定的灰度过程。从新上限到 100% 使用,期间需要通过路由功能逐步将流量引到新版本服务上。

基于上述这些特性,Monzo 最终选择了 Finagle 。它拥有上述所有特性,并且自身的模块化设计也降低了学习成本。另外,Twitter 已经使用该框架多年,说明它经受了实战的考验。刚好,在今年 linkerd 发布了,它是基于 Finagle 的进程外代理,这意味着那些不运行在 JVM 上的语言也能够使用 Finagle 的这些特性。

Monzo 将 linkerd 在 Kubernetes 上以守护集(daemon set)方式部署,这样每台服务器上都会运行linkerd 服务。应用服务首先和本机上的linkerd 服务进行交互,然后linkerd 再通过 Power of Two Choices + Peak EWMA(exponentially-weighted moving average)方式做负载均衡。该算法通过请求往返时间和请求次数加权计算均线,然后从其中选择最优的 n 个结果,再从结果集中随机挑选。这种负载均衡方式兼顾了选取最优后端,又避免了因为后端失效导致的抖动。

异步消息

Monzo 的大部分业务逻辑在后台都是通过异步消息完成的。虽然有些操作本身耗时很短,但是通过异步消息,可以更快的向用户反馈任务状态。

由于大量核心逻辑都采取了异步化,每个消息都非常重要,一个完整业务操作每个步骤的消息都不能跳过,即使发生了无法恢复的异常,整个流程也应该能够在故障修复之后继续执行下去。因此,对于异步消息架构来说,必须满足以下特性:

  • 高可用:消息发送者在发出消息之后,无需再关注消息的消费情况。即使消费者节点或者消息系统本身出现故障,该消息也必须确保被最终消费者处理。
  • 可扩展性:由于整个系统中会有大量消息流转,消息系统本身必须能够水平扩展。当业务压力过大时,可以像其他微服务一样简单的扩展消息系统的容量。
  • 持久化:在任何情况下,消息系统必须保证消息不会丢失。即使出现消息系统服务器故障,或者消费者出现故障时,消息最终也能够被消费者消费。
  • 可回放:消息系统支持回放,可以方便的重现每一个消息的处理流程,对于排查问题、故障恢复等场景非常有用。
  • 至少一次投递:消息系统首要保证消息必须被正确消费,但是要确保投递且仅投递一次基本上是不可能的,因此消息系统需要在通常情况下尽可能确保不会重复投递。

基于上述特性,在比较了多重消息中间件之后,Monzo 最终选择了 Kafka 。虽然从架构上来看,Kafka 和一般的消息中间件有着很大的不同,它更像是一个可复制的提交日志(commit log),但是它的特性刚好可以满足 Monzo 对于异步消息架构的要求。首先 Kafka 的复制和分区特性,可以满足对高可用和可扩展性的要求。其次,Kafka 的消费者仅仅维护了一个消息日志中的游标,这样可以降低发布/ 订阅模型模式的成本,另外还可以通过修改游标来重新处理过去的消息。

总结

Kubernetes、Docker、linkerd、Kafka,Monzo 通过一系列开源软件,构建了他们的 7*24 小时银行后台系统,其中的选型、运用对于其他系统也有一定的借鉴意义。


感谢郭蕾对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2016-11-29 16:165235

评论

发布
暂无评论
发现更多内容

应届女生美团Java岗4面,一次性斩offfer,我受到了万点暴击

Java 编程 程序员 架构师 计算机

数字人民币如何普惠百姓?建行发布新金融数字便民计划

CECBC

多鲸资本发布《2021教育实时音视频行业报告》:拍乐云以质取胜做行业引领者

拍乐云Pano

细节分析Linux中五种IO模型和三种实现方式

Linux服务器开发

网络编程 epoll Linux服务器开发 Linux后台开发 IO模型

【等保知识】等保测评机构申请条件,所需资料以及流程

行云管家

等保 堡垒机 行云管家 等保测评

Chaos Mesh 助力 Apache APISIX 提升稳定性

API7.ai 技术团队

lua 网关 APISIX Chaos Mesh

又一数据库高危漏洞爆出,数据安全如何有效保障?

华为云开发者联盟

redis 漏洞 GaussDB(for Redis) 开源Redis 数据库安全

揭秘Hologres如何支持超高QPS在线服务(点查)场景

阿里云大数据AI技术

Jar 组件自动化风险监测和升级实践

Qunar技术沙龙

安全 风险管理

解决智慧城市发展困扰:Web3D智慧环卫GIS系统

一只数据鲸鱼

GIS 数据可视化 智慧城市 智慧环卫

模块三作业

燕燕 yen yen

架构训练营

13张图,深入理解Synchronized

程序猿阿星

synchronized java 并发 锁机制 锁升级

从 Web 图标演进历史看最佳实践

百度Geek说

大前端

技术解码 | 腾讯云SRT弱网优化

腾讯云音视频

6月热点:BML全新升级WebIDE编程环境,度目智能视频分析盒G1上新

百度大脑

人工智能 BML

区块链不是一个风口,而是一个时代

CECBC

Ipfs国家认可吗?国家对ipfs区块链是什么政策?

区块链 分布式存储 IPFS fil

可以同时管理公有云和私有云资源的软件哪个好?

行云管家

公有云 私有云 云管平台 云资源

上架一夜遭全网封杀!阿里大牛熬夜半年手码的Java面试指南太强了

白亦杨

Java 编程 程序员 架构师

存储大师班 | NFS 的诞生与成长

QingStor分布式存储

分布式存储 分布式文件存储 NAS NFS

利用亚马逊云科技Direct Connect和Transit Gateway轻松构造企业混合云解决方案

亚马逊云科技 (Amazon Web Services)

抖音快手短视频获客软件开发系统

棒极了!可以让你Java程序快上180%以上的阿里性能优化笔记

Java架构追梦

Java 阿里巴巴 架构 面试 性能优化

kafka日志存储以及清理机制

泽睿

kafak

丰富 TF Serving 生态,爱奇艺开源灵活高性能的推理系统 XGBoost Serving

爱奇艺技术产品团队

开源 优化 tensorflow serving 推理

实战-使用 SSM 工具创建可动态扩容的存储池

学神来啦

Linux 运维 ssm Linux教程

记一次真实的JVM性能调优过程

北游学Java

Java JVM 性能调优

网络研讨会|为什么在开发流程中应用静态代码分析工具?

鉴释

在线研讨会 静态代码分析

还在使用NoSQL数据库?为IoT选择TSDB

数据库 大数据 时序数据库 tsdb 数据智能

百度AI寻人获评《新周刊》2021年度公益项目

百度大脑

人工智能 寻人

从零开始学习3D可视化之数据对接(3)

ThingJS数字孪生引擎

大前端 数据 物联网 可视化 数字孪生

Monzo是如何从0开始构建7*24小时不停歇的银行后台系统的?_语言 & 开发_金灵杰_InfoQ精选文章