淘宝Diamond架构分析

简介: 花了两天的时间研究了下Diamond,因为写得比较急,而且并没有使用过,只是单纯的做逆向建模,所以难免会有细节缺失,后面会时不时过来看看,然后做些补充。背景知识早期的应用都是单体的,配置修改后,只要通过预留的管理界面刷新reload即可。后来,应用开始拆分,从单一系统拆分成多个子系统,每个子系统还会对应多个运行实例,就开始面临一些问题: 1. 配置分散在多个业务

花了两天的时间研究了下Diamond,因为写得比较急,而且并没有使用过,只是单纯的做逆向建模,所以难免会有细节缺失,后面会时不时过来看看,然后做些补充。

背景知识

早期的应用都是单体的,配置修改后,只要通过预留的管理界面刷新reload即可。后来,应用开始拆分,从单一系统拆分成多个子系统,每个子系统还会对应多个运行实例,就开始面临一些问题:
1. 配置分散在多个业务子系统里,对同一配置的翻译在多个子系统里经常不一致。比如订单和购物车都有货币类型的配置,如果购物车上了一种新的货币类型而订单却没有相应同步增加配置项就会造成程序错误。
2. 将配置收敛成一个公有服务,可以有效改善,但是又会带来其他问题。在复杂应用里,修改一个配置项,无法确切的知道需要刷新哪些相关子系统。最终只能做全量刷新,甚至是停机发布。这对于一些停机敏感的应用例如电商几乎是无法接受的。
3. 配置收敛后,配置中心成了应用中的单点,配置如果挂了,应用也会跟着产生异常甚至挂掉。

Diamond就是为了解决这些问题,它是个高可用的配置中心。

Diamond的配置类型

配置是Diamond的核心域,也是Diamond致力于去解决的问题。Diamond有两个主要配置类型– single和aggr。二者结构如下:
配置结构
Aggr和single相比,少md5多datumId。DatumId是aggr的逻辑主键,aggr下dataId和datumId是1对多的关系,也就是说多条aggr会聚合成一条single,diamond通过merge任务对aggr合并最终生成一条single。

Md5是对content md5编码生成的字符串,用于判断缓存数据相比数据库数据是否不同,缓存数据必须严格与数据库数据一致,diamond并没有数据版本,默认数据库数据是最新的,也就是说如果数据库数据发生回退,即使缓存数据更新也会跟着回退。

Single才有md5,aggr其实并不算是完整的配置(多条aggr一起才是一个完整的配置),所以不需要校验数据是否改变。

整体架构设计

下图是Diamond的组件视图。Diamond主要有ops, sdk, client和server 4个组件。Ops是运维用的配置工具,主要用于下发以及查询配置等;server则是Diamond的后台,处理配置的一些逻辑;sdk则是提供给ops或者其他第三方应用的开发工具包;client则是编程api,它和sdk乍看有点像,其实差别很大,sdk是用于构建前台运维配置程序的,本质是对数据的维护,所有的访问和操作都是直接面向数据库的;而client则是这些数据的消费者,事实上准确的说是diamond的消费者们(各子系统)都是通过client组件对server访问。
进程视图

Diamond server是无中心节点的逻辑集群,读请求都是访问local file,而写请求则会先进入数据库,接着再更新各节点缓存。注意:ops或者其他第三方运维系统(其实就是sdk模块)读取和写入的都是数据库,这很容易理解,缓存会有lag,配置系统必须面向的是实时数据。

Diamond的数据库是单点的,这就可以利用数据库特性保证数据的原子性,一致性和持久性,也就不需要实现类似zk的集群协议,也就不存在leader/follower以及observer等节点角色,它是去中心化的,所有节点都可以接受任意请求。Diamond是典型的读多写少,写一般都来自运维系统例如ops,这种请求量会很小,即使峰值期对数据库的冲击也不会太大。实际上它就是数据库之上的一个保护壳,数据库的数据通过它透出来,也通过它渗进去。

Diamond的同质节点之间会相互通信以保证数据的一致性,每个节点都有其它节点的地址信息,其中一个节点收到变更请求后,首先写入数据库,再通知所有同质节点更新缓存,保证数据的一致性。

为了保证高可用,client会在app端以本地文件形式缓存数据的snapshot,保证即使server不可用时app也可用,这一点和dubbo很相似,所以也完全可以使用diamond搭建dubbo注册中心。

内存缓存

  • Client端使用的内存cache是一个AtomicReference

    1. 它并不是通常理解的内存缓存,而只是一个事件源,只有被监听的配置才会有cache。Cache内聚了group,dataId,md5,content和listener等。
    2. 客户端的长轮询任务(下一节将会重点介绍)只轮询被监听的配置,也就是cache的数据。客户端在pull到新数据后首先会更新snapshot,再更新cache,接着全量对比所有cache和它关联的listener的md5信息从而知道配置更新有没有被通知,没有则以cache中的内容作为消息载体通知,通知完成后更新listener的md5。
    3. 没被监听的数据不需要轮询,因为diamond提供的读数据api默认会先从服务节点获取实时数据。
  • 在客户端发起长轮询或者服务节点做dump时,都需要对比md5信息以确定是否要推送或者dump。Server端缓存全量缓存了所有配置的md5信息,并会第一时间得到更新,得到更新同时还会推送LocalDataChangeEvent。

  • 无论客户端还是服务端,内存缓存仅仅是为了满足某种功能需求,并不作为读的数据源(客户端只缓存部分数据,服务端不缓存配置内容)。这是基于产品本身定位而来的,产品定位本身就是牺牲一部分速度以降低成本,并且同时提供长轮询机制为时效性要求高的配置做到准实时的变更推送。但在客户端,每个应用的兴趣点都是分散的,平均下来每个应用感兴趣的配置数据并不大。

长轮询

Client会不断长轮询server,获取最新的配置推送,尽量保证本地数据的时效性。
长轮询

Client默认启动周期任务对server进行长轮询感知server的配置变化,server感知到配置变化就发送变更的数据编号,客户端通过数据编号再去拉取最新配置数据;否则超时结束请求(默认10秒)。拉取到新配置后,client会通知监听者(MessageListener)做相应处理,用户可以通过Diamond#addListener监听。
长轮询客户端
服务端通过AsyncContext对请求做非阻塞处理,通过定时任务感知配置变化。
长轮询server
详细描述下上图,
1. server收到请求后启动AsyncContext,并基于它构造ClientLongPulling。ClientLongPulling除了AsyncContext还有一个超时回复任务对长轮询请求做超时处理
2. 之后ClientLongPulling被加入等待列表。LongPullingService关联一个感知数据变化的定时任务,当有数据变化时(收到LocalDataChangeEvent),就会循环等待列表里的ClientLongPulling,推送数据变化回客户端。
4. Dump是抽象出来的一块儿概念,server的数据变化都会触发响应的dump task,并会发送相应的事件,由server感知,DataChangeTask也是一个事件监听者,能感知local file的数据变化。

服务端架构设计

Diamond集群是去中心化的,使用通知机制保证集群各节点数据一致。
集群数据同步
1. Diamond集群内每个节点都有其他节点的地址信息,当一台节点收到写请求后首先写数据库,接着就会发送ConfigDataChangeEvent,监听者收到该事件后通知所有节点做数据变更。通知的所有节点也包括自己,下发配置的请求只会更新数据库,并不会更新本地文件缓存。
2. 通知发送到所有节点后,通过dump更新local file。Dump是将配置对象dump进本地文件的过程,dump完毕后发送LocalDataChangeEvent,见上节。

任务管理

Diamond收到配置请求后,数据库执行完毕后,向任务管理的任务栈里插入一条任务,任务管理模块感知到新任务后,使用对应的TaskProcessor处理。TaskProcessor和Task的关系由用户调用TaskManager#addProcessor(或setDefaultProcessor)设置。因为使用队列,所以Diamond的任务管理器是FIFO的,这就会造成长延时任务阻塞其他任务的执行。

在Diamond中,为解决这个问题,给每个Task都定制了一个TaskManager。用户可以做些优化,参考hadoop的公平算法,针对应用场景(比如长延时,离线,实时等等)定制TaskProcessor。
任务管理

其他一些任务

为了保证Diamond的数据一致,除了以上介绍的两类任务,还有其他一些task,见下图:
server心跳任务
1. Merge任务用于合并aggr。App下发聚合配置到diamond后,会触发合并任务生成single,同时广播配置变更事件(ConfigDataChangeEvent),各节点收到通知后拉取数据库相应single数据并更新local file。这与上面描述的server数据同步基本类似,只是事件源头换成了merge。
merge任务
2. DumpAllTask会每6小时run一次做全量dump,全量删除老的缓存数据,生成新缓存。
2. DumpChangeTask做增量dump。通过和数据库的配置做md5对比,删除被移除配置的文件缓存,更新md5不一致的文件缓存等等。
3. 清除历史数据用于清除1周前的数据库his表数据。
4. 心跳任务用于记录心跳时间,节点服务重启时会判断距离上次心跳时间是否已经超过一小时,超过一小时则做全量dump,否则做增量。

剩下的都很好理解,不再一一介绍,需要注意的是,这些任务并不是都是定时做,有些是事件触发的,例如DumpTask和merge;还有些在Diamond服务启动时会触发,如merge,DumpChangeTask等。

相关实践学习
在云上部署ChatGLM2-6B大模型(GPU版)
ChatGLM2-6B是由智谱AI及清华KEG实验室于2023年6月发布的中英双语对话开源大模型。通过本实验,可以学习如何配置AIGC开发环境,如何部署ChatGLM2-6B大模型。
目录
相关文章
|
4月前
|
人工智能 API 数据安全/隐私保护
Apifox 与 Apipost 的 API 文档引擎对比:底层架构、性能与可扩展性分析
深入探索市场上两大主流API工具——Apifox和Apipost的文档能力时,发现了令人惊讶的差距。这不仅仅是功能多寡的问题,更关乎开发效率与团队协作的质变。
|
20天前
|
Java API 开发工具
灵码产品演示:软件工程架构分析
本演示展示灵码对复杂软件项目的架构分析与文档生成能力。通过Qwen3模型,结合PlantUML,自动生成系统架构图、微服务时序图,并提取API接口文档,实现高效、智能的代码理解与文档输出。
109 5
|
18天前
|
存储 JSON 数据处理
ClkLog埋点与用户行为分析系统:架构升级与性能全面提升
随着越来越多企业在实际业务中使用 ClkLog,数据规模和分析需求也不断提升,部分用户日活已经超过10万,为了顺应这一趋势,ClkLog 秉持 “开放透明、持续演进”的理念,推出了迄今为止最重要的一次性能优化升级。新版本在大规模数据处理与复杂查询场景中,性能表现实现了跨越式提升。经过多轮研发与严格测试,新版本现已正式上线:在原有付费版 1.0 的基础上架构全面升级,并同步发布全新的 2.0 版本。为用户带来更强的性能与更广的适用场景。
|
6月前
|
人工智能 自然语言处理 数据可视化
两大 智能体框架 Dify vs Langchain 的全面分析,该怎么选?资深架构师 做一个彻底的解密
两大 智能体框架 Dify vs Langchain 的全面分析,该怎么选?资深架构师 做一个彻底的解密
两大 智能体框架 Dify vs Langchain 的全面分析,该怎么选?资深架构师 做一个彻底的解密
|
2月前
|
存储 前端开发 JavaScript
如何开发设备管理系统中的经验分析报表板块 ?(附架构图+流程图+代码参考)
设备管理系统(EMS)助力企业高效管理设备生命周期,涵盖采购、维护到报废全流程。本文详解经验分析报表模块设计与开发,涵盖动态看板、点检、巡检、维修、保养及库存统计功能,提供代码示例与架构设计建议,提升设备管理效率与决策水平。
|
5月前
|
机器学习/深度学习 人工智能 算法
大型多模态推理模型技术演进综述:从模块化架构到原生推理能力的综合分析
该研究系统梳理了大型多模态推理模型(LMRMs)的技术发展,从早期模块化架构到统一的语言中心框架,提出原生LMRMs(N-LMRMs)的前沿概念。论文划分三个技术演进阶段及一个前瞻性范式,深入探讨关键挑战与评估基准,为构建复杂动态环境中的稳健AI系统提供理论框架。未来方向聚焦全模态泛化、深度推理与智能体行为,推动跨模态融合与自主交互能力的发展。
297 13
大型多模态推理模型技术演进综述:从模块化架构到原生推理能力的综合分析
|
9月前
|
机器学习/深度学习 安全 算法
十大主流联邦学习框架:技术特性、架构分析与对比研究
联邦学习(FL)是保障数据隐私的分布式模型训练关键技术。业界开发了多种开源和商业框架,如TensorFlow Federated、PySyft、NVFlare、FATE、Flower等,支持模型训练、数据安全、通信协议等功能。这些框架在灵活性、易用性、安全性和扩展性方面各有特色,适用于不同应用场景。选择合适的框架需综合考虑开源与商业、数据分区支持、安全性、易用性和技术生态集成等因素。联邦学习已在医疗、金融等领域广泛应用,选择适配具体需求的框架对实现最优模型性能至关重要。
1616 79
十大主流联邦学习框架:技术特性、架构分析与对比研究
|
4月前
|
运维 监控 数据可视化
一文详解:工业软件“低代码开发平台”技术架构研究与分析
本文围绕工业软件低代码开发平台的机遇与挑战,提出基于自动化引擎的技术架构,由工具链、引擎库、模型库、组件库、工业数据网关和应用门户组成。文章分析了其在快速开发、传统系统升级中的应用模式及价值,如缩短创新周期、降低试错成本、解决资源缺乏和提升创新可复制性,为我国工业软件产业发展提供参考和支持。
|
4月前
|
负载均衡 Java API
基于 Spring Cloud 的微服务架构分析
Spring Cloud 是一个基于 Spring Boot 的微服务框架,提供全套分布式系统解决方案。它整合了 Netflix、Zookeeper 等成熟技术,通过简化配置和开发流程,支持服务发现(Eureka)、负载均衡(Ribbon)、断路器(Hystrix)、API网关(Zuul)、配置管理(Config)等功能。此外,Spring Cloud 还兼容 Nacos、Consul、Etcd 等注册中心,满足不同场景需求。其核心组件如 Feign 和 Stream,进一步增强了服务调用与消息处理能力,为开发者提供了一站式微服务开发工具包。
497 0
|
安全 数据处理 数据安全/隐私保护
C/S架构与B/S架构的适用场景分析
C/S架构(客户端/服务器架构)与B/S架构(浏览器/服务器架构)在适用场景上各有特点,主要取决于应用的具体需求、用户群体、系统维护成本、跨平台需求等因素。
961 6