学习极客时间-左耳听风专栏的个人学习记录。
分布式架构
分布式架构基础
为什么需要从单体->分布式架构
- 增加系统容量:随着业务量级的增加,单体机器不足以支撑。需要通过横向或纵向分割来拆分。
- 可用性:防止单点故障
分布式架构的优势和劣势
优势:
- 模块化,所以重用度更高
- 拆分后维护粒度更合适,便于开发协作、并行开发
- 扩展性更高 劣势(带来的问题):
- 架构设计复杂,部署、维护、管理成本更高 - 所以需要更成熟的管理方式
- 学习成本高
- 系统吞吐量大、响应时间会更长
- 测试和差错成本增大
分布式架构的发展(其实还是延续SOA的思想)
- 较耦合,一个服务调用另一个服务
- 通过一个中间件,用一套统一的规范(如ESB),使得不同构件之间不是直接调用,是通过统一的类似中转站的方式
- 微服务,松耦合。更是需要成熟的微服务PaaS来支撑良好的部署、管理、配置、调度等
从亚马逊的实践,谈分布式系统的难点
亚马逊关于分布式的实践、难点、解决
亚马逊关于分布式的实践是非常早的,为此他们定义了一些架构规范:
- 所有团队的模块都要通过 Service Interface 方式将其数据与功能开放出来
- 不同模块的通信都要通过这些接口
- 除了这种形式的通信,其他方式都不允许(如直接读取其他模块的数据库、链接别的程序、使用共享内存等)
- 任何技术都可以使用。比如:HTTP、CORBA、Pub/Sub、自定义的网络协议等。
- 所有的Service Interface 都秉承开放的原则,以便未来把接口开放给全世界的程序员
AWS (Amazon Web Service)
在这个过程中,为了解决分布式带来的诸多问题(上个小章节提到的),亚马逊内部也做出了很多实践进行解决:
- 分布式系统需要分布式的团队架构:团队组成不是以技术栈为单位,是以服务为单位的(以职责分工,不是以技能分工)。人数在16人左右(两张pizza可以喂饱的程度)。
- 没有专门的测试、运维人员,开发全包。为自己写的代码从头到尾负责,这样在开发时就会考虑到长期的维护性。
- 分布式查错不容易:因此遇到问题时,一般是关联系统都会签到自查自己的系统。暂时没发现问题,也要待命。
- 运维优先,投入很多到运维方面,才能支撑起这么复杂的架构运行。对系统进行简化和自动化。
- 内部服务和外部服务一样对待:内部服务可以随时开放出来
分布式系统需要注意的问题
异构系统的不标准
异构系统的技术栈、数据格式、通信方式、开发方式的不同,对于分布式的统一规范是个挑战。需要遵遁一定的标准才能真正统一管理起来。
关于配置管理,建议分成三层:
- 底层和操作系统相关
- 中间层和中间件相关
- 最上层和业务应用相关 最上层的配置可以开放给用户选择,而下面两层的配置建议封装成模版供人选择,才能形成规范,否则难以管理。
关于数据通讯协议,应该分为协议头和协议体。协议头应该形成规范,规定统一的字段(便于规范、监控、管理等)。协议体是业务内容,可以自己指定。
服务依赖性问题
服务是有依赖性的,一条依赖线上的服务挂掉,可能形成多米诺骨牌。
要警惕:
- 若关键服务依赖于一个非关键服务,那么这个非关键服务也成了关键服务
- 木桶短板效应:一条链上的性能等会依赖于最短版的那个服务
因此,服务管理需要关注的服务的关键程度和依赖关系、主要路径。
故障发生的概率更大
单体应用和分布式应用的故障有所不同:
- 单体应用:一般挂了就全挂,影响大
- 分布式应用:某个节点挂了影响可控,但是因为架构复杂,所以故障的概率更大
因此如果更好的管理分布式系统,在预防和救治故障过程中都要设计好。否则,会被频繁的故障搞崩溃。
- 关键监控指标
- design for failure
多层架构运维复杂度更大
一般系统分为四层:
- 基础层:机器、网络、存储设备等
- 平台层:中间件
- 应用层:服务
- 接入层:用于请求的网关
需要明确:
- 任何一层出问题都会给整体带来问题
- 需要统一的管理视图和配置标准,不能是各管一个区域,没有协同考虑整体。如某个参数配置,各层要统一,否则对于故障发生和纠错都是个雷点
分布式系统的技术栈
分布式的两个主要目的
- 提高系统容量、吞吐量、性能
- 提供稳定性
目的对应的常用技术
针对第一点:容量
- 缓存: 缓存系统 缓存分区、缓存命中、缓存更新
- 负载均衡: 网关系统 负载均衡、服务路由、服务发现
- 异步调用: 异步系统 消息队列、消息持久、异步事务
- 数据库镜像: 数据同步、读写分离、数据一致性
- 数据分区: 分区策略、数据访问性、数据一致性
针对第二点:稳定性
- 服务拆分: 服务治理 服务调用、服务依赖、服务隔离
- 服务冗余: 服务调度 弹性伸缩、故障迁移、服务发现
- 限流降级:限流降级 异步队列、降级控制、服务熔断
- 高可用架构: 高可用架构 多租户系统、灾备多活、高可用服务
- 高可用运维(CI/CD): 运维系统 全栈监控、DevOps、自动化运维
5个分布式关键技术
- 全栈系统监控
- 服务/资源调度
- 数据/状态调度
- 流量调度
- 开发和运维的自动化
分布式关键技术——全栈监控
监控的三个层级
- 基础层:CPU、内存、网络吞吐、硬盘IO、硬盘使用
- 中间件层:中间件,比如:Nginx、Redis、ActiveMQ、Kafka、MySQL、Tomcat 等
- 业务应用层:HTTP 访问的吞吐量、响应时间、返回码、调用链路分析、性能瓶颈,还包括用户端的监控
怎样算一个好的监控系统
需要一些标准化和统一视图
一个好的监控系统特征:
- 整体的SLA:从用户的API来监控整个系统
- 关联指标聚合展示,具体实例和主机指标关联展示
- 用户请求跟踪的 trace 监控,快速定位故障
SLA 是 Service Level Agreement 的缩写,简单一句话解释:
它是服务提供商向客户承诺的服务质量最低标准(如可用性、响应时间等)。
怎么实现一个好的监控系统
- 服务调用链追踪
- 服务调用时长分布
- 服务的Top N视图(调用量、调用时长(耗时)、热点排序)
- 数据库操作关联(如以慢查询排序列出相关的接口)
- 服务资源跟踪 根据这些监控信息,就可以很快定位出是哪块除了问题,然后根据这些故障信息做自动化调度(如弹性伸缩、降级等处理)
分布式关键技术——服务调度
服务的关键程度和依赖关系
梳理服务的关键程度和依赖关系,可以了解“城市的主干道、关键设施、拥堵情况等“
微服务是服务依赖最优解的上限,服务依赖的下线是千万不要有依赖环
解决依赖环的方案一般是:倒置依赖的设计模式 [[【学习笔记】极客时间-左耳听风(陈皓)之技术基础#其他-关于循环依赖使用依赖倒置解决]]
服务的状态和生命周期的管理
服务注册中心:因为服务是动态的(新增、离开、伸缩等),版本变化,服务的当前状态
服务的生命周期状态:
- provision 供应一个新的服务
- ready 启动成功了
- run 通过了健康检查
- update
- rollback
- scale (including scale-in and scale-out) 伸缩中
- destroy
- failed
整个架构的版本控制
不同于单个服务的版本控制,在整个架构的上面再加一个整理的版本,控制各个服务的版本兼容。如果要回滚一个服务的版本,就要把有版本依赖的服务都回滚掉。
要实现架构的版本控制,需要一个服务清单 mainfest。其中包括:
- 软件版本
- 运行环境——环境变量、cpu、内存、文件系统等
- 服务运行的最大最小实例数
- 等等
关于manifest
简单来说,“架构的 Manifest” 就是一份用结构化语言写成的、版本化的、声明式的清单/蓝图。它精确地描述了软件系统或基础设施应该是什么样子(What),而不是具体怎么做(How)。它是现代 DevOps 实践、基础设施即代码、云原生架构和自动化部署的基石。当你看到 Kubernetes YAML、Terraform
.tf文件、Ansible Playbook 或package.json时,你看到的就是不同语境下的“架构 Manifest”。
资源/服务调度
关于服务状态的维持和拟合
这里指的服务状态,是服务运行周期的状态 [[【学习笔记】极客时间-左耳听风(陈皓)之技术基础#服务的状态和生命周期的管理]]
服务状态变化一般有两种:
- 非预期的,比如因为一些服务挂掉。而一个好的集群管理控制器应该努力维护期望的服务状态,也就是摘除不健康的,启动新的服务。——这也就是【维持】
- 预期的,比如服务在部署需要伸缩。控制器需要将集群从现有状态转换为另一个新的状态, 这是一个过程。集群控制器需要一步一步地向集群发送若干控制命令。这个过程叫“拟合” [[【学习笔记】极客时间-左耳听风(陈皓)之技术基础#关于服务状态的【拟合】]]
服务的弹性伸缩和故障迁移
弹性伸缩涉及:底层资源的伸缩;服务的自动化部署;服务的健康检查;服务发现的注册;服务流量的调度等
关于故障迁移:对于服务来说,有两种模式:
- 宠物模式:独一无二、宝贵;出现问题:救活它;适用于有状态服务
- 奶牛模式:可替代的牲畜;出现问题:替代它;适用于无状态服务 ; 这是云原生架构更推崇的
两者的对比:
| 特性 | 宠物模式 (Pets) | 奶牛模式 (Cattle) |
|---|---|---|
| 哲学 | “救活它!” | “替换它!” |
| 适用服务类型 | 有状态 (Stateful) | 无状态 (Stateless) |
| 实例唯一性 | 高(有名称、固定标识) | 低(匿名、可批量替换) |
| 状态存储位置 | 本地(磁盘/内存) | 外部(DB、缓存、网络存储) |
| 故障恢复策略 | 修复 (Heal) | 替换 (Replace / Recreate) |
| 自动化程度 | 较低(常需人工) | 极高(全自动) |
| 恢复时间 (RTO) | 较长(依赖修复复杂度) | 极短(秒级重建) |
| 扩展性 | 较难(需考虑状态迁移) | 极易(直接增减实例) |
| 典型基础设施 | 物理机、虚拟机 | 容器(Docker)、Serverless |
| K8s 控制器 | StatefulSet |
Deployment |
故障恢复:
- 服务的健康监控(这可能需要一个 APM 的监控)。
- 如果是宠物模式,需要:服务的重新启动和服务的监控报警(如果重试恢复不成功,需要人工介入)。
- 如果是奶牛模式,需要:服务的资源申请,服务的自动化部署,服务发现的注册,以及服务的流量调度。
服务工作流和编排(Service Orchestration)
两个核心概念:服务编排和统一入口
- 服务编排
在微服务架构中,一个客户端请求可能需要调用多个后端微服务才能完成。协调这些服务调用顺序、处理依赖、聚合结果、处理错误的过程就叫“服务编排”。
实现方式:
- API 网关,作为唯一接受不了客户端请求的入口
- 消息队列,适合更负责、需要解耦的流程
- 统一入口
客户端不应该直接访问内部成百上千个微服务实例。应该通过一个单一的、受控的入口点来访问整个系统。
特点:
- 客户端只需知道网关地址
- 安全:由网关统一做认证、授权
- 前后端解耦
- 横切关注点集中处理: 在网关层统一实现限流、熔断、日志、监控、SSL 终止、路径重写等。
- 服务发现集成
其他-关于循环依赖使用依赖倒置解决
AI给出的简单比喻:
- 循环依赖: 就像三个人(A, B, C)围成一圈传球,每个人都必须把球传给下一个人才能开始自己的动作,结果球一直在传,没人能真正开始做事(死锁)。
- 依赖倒置: 大家约定好一个传球规则手册(接口),手册放在中间。A按手册要求把球扔向某个位置(调用接口),B按手册要求去那个位置接球(实现接口)。A不需要知道接球的是B还是别人。
- 消息中间件: 大家不再互相传球。A把球放进一个公共的邮筒(MQ),邮递员会负责把球送到需要处理球的人(B)家门口的邮箱里。B处理完球后,也把结果放进邮筒,邮递员会送给需要结果的人(可能是A,也可能是C)。A和B不需要知道对方住哪。
- 第三方协调服务: 请一个教练(Service X)。A拿到球后,直接把球传给教练X。B需要球时,也问教练X要。教练X负责决定什么时候把球给A、什么时候给B、让他们做什么动作。A和B只负责听教练的指令和完成自己的基础动作(接球、投篮等),不需要关心队友在干嘛。
其他-关于“服务注册”
大概了解了下服务注册,首先这里的服务不是接口,是指提供接口的实例,也就是我们后端服务。注册的内容是后端实例的地址(ip:port),同一个服务可以注册多个实例(实现负载均衡)。注册的目的是为了让后端服务之间可以找到彼此,以及给前端调用时找到使用的。
前端是无需注册的,因为前端主要是通过API网关访问后端(网关从注册中心获取后端服务实例,并路由请求)。
关于服务状态的【拟合】
拟合的概念是比较抽象的,指的是编排器努力实现逼近目标状态。一方面是因为服务的编排是“声明式”的,而不是“命令式”的,编排器会根据目标不断的去协调循环,多次循环才能实现最终的目标;一方面是因为服务状态的转换是动态的,外部和pod自身的状态转变都在发生,需要时间。
- “集群状态的变更不应该很明确吗?” 是的,目标状态是非常明确的(比如“10个健康的Nginx 1.25实例”)。但是达到和维持这个目标状态的过程,在复杂、动态、可能出错的现实世界中,不可能是瞬间完成的、一帆风顺的、一蹴而就的。它必然是一个需要处理各种约束、协调、等待、重试、纠错的“拟合”过程。
- “怎么看它的描述有点抽象”: 因为它描述的是控制系统背后的通用原理和持续行为模式,而不是某个具体操作的细节。理解了这个“拟合”的过程,你就理解了像Kubernetes这样的集群编排系统最核心的自动化管理机制。
分布式关键技术——流量与数据调度
流量调度
主要功能
- 提高系统的稳定性和高可用性
- 无需人工干扰情况下,自动进行流量调度
- 应对突发高并发的情况下,还可以平稳运行
- 服务流控:服务发现、服务路由、服务降级、服务熔断、服务保护等。
- 流量控制:负载均衡、流量分配、流量控制、异地灾备(多活)等。
- 流量管理:协议转换、请求校验、数据缓存、数据计算等。
关键技术
也就是一个好的API Gateway要具备的关键技术:
- 高性能
- 抗流量:集群技术
- 业务逻辑:可支持注入简单业务逻辑
- 服务化:可不停机的管理配置变更
状态数据调度
对于服务调度来说,难办的就是“有状态”的服务(有些服务会保存数据,而这些数据不能丢失)。一般,我们会转移状态到第三方的服务上,将我们的Java等变成无状态的,但是转移到的Redis或Mysql等就变成有状态了。于是问题就转移到了如何调度这种有状态的数据存储节点上。
解决数据不丢失的问题,一般是(可以说是唯一手段):制造数据副本(数据冗余)- 解决数据不一致问题 - 从而又引起性能问题
解决数据不一致问题:
- master-slave
- master-master
- 两阶段和三阶段提交方案
- paxos方案
AI关于paxos的解释:
想象一群人在一个嘈杂的房间里决定晚餐吃什么(值 V)。
- 准备阶段(举高手牌): 有人说:“我要提议!我的编号是 55(当前最高)!同意的举手,并告诉我你们之前同意过的最高编号提议是什么?” 大多数人举了手,其中有人喊:“我们之前同意过编号 40 的提议吃披萨!”
- 接受阶段(正式提议): 提议者听到有人说披萨(
V),就说:“好!我现在正式提议编号 55,我们吃披萨(V)!同意的请确认!” 那些没承诺过更高编号提议的人(大部分)都同意了。于是“吃披萨”被多数人接受,成为最终决定。 - 解决不一致: 如果有人之前在小范围(但达到了多数)内偷偷同意过编号 40 的“吃披萨”,或者编号 30 的“吃汉堡”被另一小部分人同意过(但未达到多数),当新提议者(编号 55)在准备阶段询问时,那些知道“吃披萨”的人会报告出来。新提议者必须选择这个披萨提案来继续推进,确保最终大家都统一到“吃披萨”上,而“吃汉堡”就被抛弃了。如果没人报告历史值,新提议者就可以自由提议(比如“吃寿司”)。
对于应用层上的分布式事务一致性,只有两阶段提交这样的方式。
参考: 分布式系统的事务处理
关于上述链接内容的学习:
扩展数据服务的一般方法
- 数据分块 分块(chunking/blocking)和分区(partitioning)是不同的概念:分区是按照业务规则将一张大表拆成独立的小表,实现优化查询效率的目的等。如按日期分区、按哈希分区(均匀分散数据,分布式数据库);分块是纯技术导向,将数据按照固定大小或技术维度拆分多个物理存储单元
- 数据冗余(镜像):可解决单台数据库挂掉数据丢失的问题
数据不一致问题
以经典的转账问题为例:从A账户转账到B账户,涉及A账户金额减少、B账户金额相应增加。并且这两个过程应该是原子性的,回滚时需要同时回滚
- 数据分块场景:若A账户数据和B账户数据在不同的服务器上,如何保证跨机器的事务处理
- 数据镜像场景:A、B账户的数据可以在同一个机器上,但是镜像机器的更新不是同时的。如果A账户需要向B和C账户汇款,而这个过程在不同的服务器上触发执行的话,对A账户的写操作怎么保证一致性,保证数据不冲突
数据冗余情况下的问题考虑
为解决数据丢失问题,几乎唯一的手段是数据冗余,因为主要需要考虑数据冗余的场景下的数据一致性和性能问题: 高可用性 -> 多份数据 -> 数据一致性问题 -> 性能问题
一致性模型
- weak 弱一致性: 新值写入,数据副本可能读到,可能读不到
- eventually 最终一致性: 新值写入,数据副本可能读到,可能读不到,但在某个时间节点一定会读到
- strong 强一致性:新值一旦写入,各处可读
前两种是异步冗余,最后一种是同步冗余
数据冗余算法(异步or同步)
- master-slave 一般设计是:
- 读和写请求都由master来处理
- 写在maser处理后,由master同步到slave(异步or同步)
- master push 到 slave
- slave 从 master pull 要实现master-slave是强一致性的话:可以只有等slave也写入成功后,才返回整体成功:
- 失败的slave标记不可用并继续服务
- 回滚master (为什么不先写到slave: “先写Master”是标准且安全的设计。避免“先写Slave”方案的主要原因正是为了防止陷入需要回滚Slave的复杂且危险的境地,而这种危险在“先写Master”方案中(对于Master本地写入失败的情况)是根本不存在的。)
- master-master
意味着有两个或多个master(也可称为
multi-master)都可进行读写,然后不同master之间进行异步数据同步(也就是实现最终一致性)。如果有master节点同步失败,可将其剔出服务,重试写入。
但是多个master同时支持写入,需要注意的问题是写入冲突(id冲突、唯一索引冲突等)。推荐的是预防方式:如通过路由方式将同类数据的写都导向同一个master来执行。如果还是遇到了冲突,可采用时间戳/版本号等决出方式、应用层解决等方式。
- 2/3 PC (phase commit) - 两段/三段提交 - 强一致性 先说两段提交: 由于分布式各节点无法知道其他节点的执行结果,此方法引入一个协调者角色,相应的分布式上的节点作为多个参与者。一个请求可以分为两个阶段:
- 阶段一(vote):协调者问各个参与者,是否可以执行提交操作;各个参与者开始进行准备工作,如给资源上锁、写undo/redo log、预留资源等;如果都准备好了,回复“可以提交”,否则回复“拒绝提交”
- 阶段二(decide):协调者根据各参与者回复的结果
- 若全部都是可以提交,则通知各节点执行提交。各节点提交完成后,释放资源,回应“完成”,协调者收集所有“完成”回应后结束这个global transaction;
- 否则,通知各节点回滚。各节点回滚后,释放资源,回应“回滚完成”。协调者收集到所有回应后,取消这个global transaction
两段提交的问题: 1、同步会阻塞操作,影响性能 2、timeout 问题
关于timeout问题,可以有好几种情况: 1、第一阶段时,参与者没有收到协调者的请求;或者协调者没有收到参与者的回应 2、第二阶段时,正式提交请求发出后,部分参与者没有收到请求;或者参与者发出的完成回应没有被协调者收到。没有成功参与的参与者可能被剔除或重试 3、【最大的问题】第二阶段时,如果参与者都没有收到协调者的提交请求(比如协调者挂掉),这时参与者都会处于不出所措的情况,会block住整个事务。 - 也就是协调者的可用性很重要
由此引入了3PC(也就是把一阶段拆成两步),它的核心思想是:在询问时不锁定字段,只有等到所有人都同意了,才开始锁资源。如果在PreCommit时(即P状态,也就是明确所有参与者都同意时)出现了失败或超时的情况,各参与者会直接commit,而不是像2PC一样不知所措。
以下是ai举的例子: 为什么 3PC 在 P 状态故障时能继续 Commit?
- 2PC 的“已投票锁定”状态: 参与者 只知道自己的投票(Yes),不知道其他参与者的投票结果。当协调者消失时,参与者无法判断全局状态:是所有节点都投了 Yes?还是协调者看到了某个 No 才崩溃的?因此不敢擅自 Commit 或 Abort,只能阻塞等待。
- 3PC 的
PreCommit(P) 状态: 这个状态是一个 全局共识状态。参与者进入P状态 需要两个条件:- 自己投了 Yes。
- 明确知道所有其他参与者也都投了 Yes(因为协调者只在收到所有 Yes 后才会发 PreCommit)。
- 因此,当协调者在
P状态后故障时:- 每个处于
P状态的参与者都 100% 确定 事务在所有节点上都已达成提交共识。 - 既然共识已定,且没有收到 Abort 指令,那么继续推进到
Commit状态就是 安全的、一致的 行为。不需要再依赖协调者。
- 每个处于
3PC虽然在协调者挂了后可以继续commit,但是诸如这类失败场景难以避免:
缺乏最终操作的协调: 在协调者存活时,如果某个参与者在收到 Commit 后报告失败,协调者可以尝试重试或发起补偿(回滚)指令(虽然回滚也可能失败,但至少有协调)。但在协调者故障且参与者自行 Commit 的场景下,没有任何机制来协调处理参与者C的失败。参与者A和B已经成功提交,无法回滚;参与者C失败了。系统失去了统一协调者。
这种情况的解决手段(也不算完美解决手段,只是有这些尝试解决的方案):
- 人工干预,运维人员发现不一致后手动修补
- 设计失败节点重试机制
- 业务逻辑补偿:如系统检测到不一致,则回滚其他节点或生成一个补偿业务操作
- 采取其他同步机制
- two generals problem 两将军问题 以及 plus版本:拜占庭将军问题 (Byzantine Generals Problem)
文中只是阐述了问题的描述。以下是ai给出的总结:
| 问题类型 | 解决方案 | 容错能力 | 适用场景 |
|---|---|---|---|
| 两将军问题 | TCP超时重传 | 信道丢失(非恶意) | 网络通信(如TCP连接) |
| 拜占庭问题 | PBFT | N≥3F+1N≥3F+1 恶意节点 | 联盟链、金融系统 |
| 区块链(PoW/PoS) | 经济惩罚约束恶意行为 | 公链(如比特币、以太坊) |
- Paxos算法 核心目的:让整个集群针对某个值的变更达成一致
手段:通过民主选举的算法,任何一个节点可以提出修改的提案,只要有超过半数的节点同步就可以修改。因此节点的数量一般要是奇数。其中有个概念是提案号,它是每个提案的唯一编号且一定是递增的。
Paxos算法可以看作是2PC的plus版本,也分为两阶段:
- 第一阶段(prepare):某节点提出变更方案发给所有节点(需要带上提案号
n),各节点判断当前手头的提案号如果都小于最新收到的这个提案,就回复同意(并保证不接受其他更小的提案编号);否则,否决。- 优化:在上述 prepare 过程中,如果任何一个结点发现存在一个更高编号的提案,则需要通知 提案人,提醒其中断这次提案。
- 第二阶段(accept):如果超过半数的节点都回复同意,则此提案通过,向各节点发送accept request(带上提案编号
n)。当各节点收到后,再次确认手头是否n编号是最大的,如果是的话就生效,否则拒绝修改。
我们还可以看到:对于同一个值的在不同结点的修改提案就算是在接收方被乱序收到也是没有问题的。
需要厘清的是,上面虽然写的是对某个值的变更,但实际上是对【系统的一个完整状态快照】的变更(如v={a:1, b:2})。不同实例是完全隔离的,如实例B不知道实例A修改过什么值。因此,需要事务操作的步骤(如转账问题),可以通过将关联操作都放在同一个实例、通过日志序列+状态机串行化操作等方式加以解决。
数据节点的分布式方案
真正解决数据结点调度的方案应该是底层的数据结点。在它们上面做这个事才是真正有效和优雅的。
真正完整解决数据 Scale 问题的应该还是数据结点自身。只有数据结点自身解决了这个问题,才能做到对上层业务层的透明,业务层可以像操作单机数据库一样来操作分布式数据库,这样才能做到整个分布式服务架构的调度。 也就是说,这个问题应该解决在数据存储方。但是因为数据存储结果有太多不同的 Scheme,所以现在的数据存储也是多种多样的,有文件系统,有对象型的,有 Key-Value 式,有时序的,有搜索型的,有关系型的……
洞悉PaaS平台的本质
一家好的公司的软件工程能力可体现在三方面:
- 提高SLA
- 高可用
- 自动化运维
- 可重用
- 模块
- 环境和资源
- 自动化
- 生产流水线
- 运维自动化
以上特质都可以在PaaS平台上得到完全体现。
在 Docker+Kubernetes 层之上,我们看到了两个相关的 PaaS 层。一个是 PaaS 调度层,很多人将其称为 iPaaS;另一个是 PaaS 能力层,通常被称为 aPaaS。没有 PaaS 调度层,PaaS 能力层很难被管理和运维,而没有 PaaS 能力层,PaaS 就失去了提供实际能力的业务价值。
完整的PaaS平台会包含以下几部分:
- 调度层:自动化、分布式的高可用高性能管理
- 能力调度层:提供给用户的服务和能力
- 流量调度
- 运营管理
- 运维管理
分布式推荐阅读和论文
内容很多,此部分需要用时再说