乐趣区

关于后端:计算存储分离在京东云消息中间件JCQ上的应用

作者:田寄远

JCQ 全名 JD Cloud Message Queue,是京东云自研、具备 CloudNative 个性的分布式消息中间件。JCQ 设计初衷即为适应云个性的消息中间件;具备高可用、数据可靠性、正本物理隔离、服务自治、衰弱状态汇报、少运维或无运维、容器部署、弹性伸缩、租户隔离、按量付费、云账户体系、受权等个性。

演进过程

2017 年中开始开发 JCQ 1.0 版本,2018 年 11 月正式 GA 上线对外售卖,1.0 版本中 Topic 受限于单台服务器限度,满足不了用户超大规格 topic 的需要。

2019 年 4 月 JCQ 2.0 正式上线,次要新增个性是 topic 扩缩容能力、热点 Topic 在 Broker 间的负载平衡、热点 Broker 的流量转移。

2019 年 7 月 JCQ 做了一次大的架构演进 —— 计算存储拆散,大版本号为 JCQ 3.0, 于 2019 年底上线。计算存储拆散对架构带来了比拟显著的益处,解决了日常遇到许多的痛点问题。下文具体介绍此次演进带来的益处及解决的痛点问题。

降级影响范畴尽可能小

在 JCQ2.0 中计算模块与存储模块处于同一个过程,降级计算模块势必将存储模块一起降级。而存储模块重启是比拟重的动作,须要做的工作有:加载大量数据、进行音讯数据与音讯索引数据比对、脏数据截断等操作。往往修复计算模块一个小的 Bug,就须要做上述十分重的存储模块重启。而在事实工作中,大部分降级工作都是因为计算模块性能更新或 Bugfix 引起的。

为了解决这个问题,JCQ3.0 将计算模块、存储模块独立部署,之间通过 RPC 调用。各自降级互不影响。如下图所示:

计算节点 Broker 只负责生产音讯、推送音讯、鉴权、认证、限流、拥塞管制、客户端负载平衡等业务逻辑,属于无状态服务。比拟轻量,降级速度快。

存储节点 Store 只负责数据写入、正本同步、数据读取。因为业务逻辑简略,性能稳固后,除优化外根本无需改变,也就无需降级。

老本升高

JCQ 是共享消息中间件,用户申请的是不同规格 TPS 的 Topic,并不感知 cpu、memory、disk 等硬件指标。所以,JCQ 服务方须要思考如何正当的应用这些硬件指标。

JCQ 是容器部署,有多种类型的组件,这些组件对硬件的需要也是多样化的,其中对资源耗费最多的是计算模块和存储模块。在 JCQ2.0 版本计算模块和存储模块部署在一起,抉择机型时要兼顾 cpu、memory、disk 等指标,机型要求繁多,很难与其余产品线混合部署。即便是同一资源池,也存在因为调度程序,造成调度失败的状况。如一台机器残余资源恰好能调度一个须要大规格磁盘的 A 容器,然而因为 B 容器先被调度到这台机器上,残余资源就不够创立一个 A 容器,那这台机器上的磁盘就节约了。

JCQ3.0 后,计算节点 Broker,与存储节点 Store 独立部署。这两个组件能够各自抉择适宜本人业务的机型,部署在相应资源池中;最终,能够做到与其余产品混合部署,共用资源池水位,而不必单独承当资源水位线。

 

架构改良带来的老本升高

JCQ3.0 中计算节点 Broker 是无状态服务,主从切换比拟轻量,能在秒级实现故障转移;且部署时思考了物理设施反亲和,如跨 Rack、跨 AZ 部署。所以,能够在可用性、资源老本之间做肯定的衡量;如能够应用 M:1 形式做高可用冷备,而不用 1:1 的比例高可用冷备,进而达到节俭硬件资源的目标。

 

解决 Raft 性能问题

JCQ 1.0 设计之初就采纳 Raft 算法,来解决服务高可用、数据一致性的问题。Message Log 与 Raft Log 有很多独特的个性,如程序写、随机读、末端热数据。所以,间接用 Raft Log 当成 Message Log 是十分适合的。

在 JCQ 演进中咱们也发现了 Raft 自身的一些性能问题,如程序复制、程序 commit、有的流程只能用单线程解决等限度。针对这些问题,最间接无效的方法就是扩大 Raft 的数目、扩大单线程流程数目,在肯定数量级内,并发能力随着 Raft Group 数目的增长,呈线性增长关系,称之 MultiRaft,如下图所示。

**

 

上图中,每个 StoreNode 节点是一个独立过程,外部有四组逻辑 RaftGroup(橙色的节点为 RaftGroup 的 Leader),各组 RaftGroup 之间是并行关系,能够做到 Group 间并行复制、并行 commit。

因为大量应用了 NIO,这些 RaftGroup 之间能够共享通信线程池,裁减 RaftGroup 数目并不会带来线程资源线性增长的问题。

疾速故障复原、轻量的负载平衡

在 JCQ3.0 中,Broker 为轻量的无状态服务,在主从切换、故障复原方面绝对 2.0 更为轻量,自身能更快的复原对外服务能力。

同时,Broker 将 Producer、Consumer 的连贯申请,形象为 PubTask 和 SubTask,后文统称为 Task。Task 的概念十分轻量,仅形容 Client 与 Broker 的对应关系,由元数据管理器 Manager 对立调度、治理。转移 Task 只须要批改 Task 的内容,客户端从新连贯新 Broker 即可。

一般来说,Broker 的次要瓶颈在于网络带宽。Broker 定期统计网络入口流量与进口流量,并上报给治理节点 Manager。Manager 依据入口流量、进口流量与带宽阈值进行裁决,发现超过阈值后,通过肯定策略将相应的 Task 转移到较小负载的 Broker 上,并告诉相应的 Producer 与 Consumer;Producer 与 Consumer 收到告诉后,从新获取 Task 的路由信息,主动重连到新的 Broker 持续进行生产、生产。

 

高扇出需要

构想一个场景,有一个大规格的 topic,创立了 n 个生产组。生产总 TPS 是生产总 TPS 的 n 倍。减少生产组,会导致生产总 TPS 线性增长。达到肯定生产组规模后,单 Broker 因为网卡带宽的起因,无奈满足这种高扇出的场景。单服务器是无奈解决这个问题。

在 JCQ 3.0 能够将这些不同的生产组对应的 SubTask 扩散到若干个 Broker 上,每个 Broker 负责一部分 SubTask,单 Broker 从 Store 预读音讯,将数据推送给 Consumer。这样多个 Broker 共同完成所有生产组的音讯流量,合作一起提供高扇出的能力。

反对多种存储引擎

消息中间件很大的特点是:大部分场景下,热数据都在末端,而回溯几天之前的音讯这个性能是不罕用的。所以,就有冷热数据之分。

JCQ 计算节点设计了一层存储形象层 Store Bridge 能够接入不同的存储引擎,能够接入 Remote Raft Cluster,或者分布式文件系统 WOS、或者 S3。甚者能够将冷数据定期从低廉的本地盘卸载到便宜的存储引擎上。

副作用

绝对于 JCQ2.0,计算节点与存储节点之间的通信形式,由接口调用变为 RPC 调用,在提早方面会有肯定损失。通过测试,绝大部分提早都在 1ms 左右,在大多数场景下 就义 1ms 左右的提早并不会给业务带来太大的影响。

后续倒退布局

JCQ 后续会次要在多协定兼容,按需主动扩缩容、云原生等方面演进。

多协定兼容

JCQ 协定为公有协定,在疏导用户迁徙方面有比拟大的阻碍。后续会抽离 JCQ Kernel,内部提供不同的协定接入层。不便用户从其余 MQ 接入 JCQ。目前已兼容 RocketMQ 协定,SQS 协定

主动扩缩容

JCQ 是共享消息中间件,但短少 Serverless 主动扩缩容的个性。每逢大促,如 618,双 11,服贸会等重要流动。业务方很难预估本人的业务量峰值,或者估计不足,会造成 topic 限流等问题。如在保障 JCQ 服务自身能力状况下,能做到 topic 灵便的主动扩缩容,将对用户有极大的帮忙,起到真正的削峰填谷作用。

云原生

反对在 kubernetes 环境部署与交付,提供原生的 Operator,可能疾速的部署在 k8s 环境中,更好的交付公有云、混合云我的项目。

退出移动版