QCon 演讲火热征集中,快来分享技术实践与洞见! 了解详情
写点什么

分布式系统关注点——“无状态”详解

  • 2019-01-24
  • 本文字数:2433 字

    阅读完需:约 8 分钟

分布式系统关注点——“无状态”详解

本文中我们开始聊一些让系统更简单,更容易维护的东西——“易伸缩”,首当其冲的第一篇文章就是“stateless”,也叫“无状态”。

一、初识“状态”

我们首先举个例子。


开发 Z 哥对运维 Y 弟喊:“Y 弟,现在系统好卡,刚上了一波活动,赶紧帮我加几台机器上去顶一下。”


Y 弟回复说:“没问题,分分钟搞定”。


然后就发现数据库的压力迅速上升,DBA 就吼了:“Z 哥,你丫的搞什么呢?数据库要被你弄垮了”。


然后客服那边接框也爆炸了,越来越多的用户说刚登陆后没多久,操作着就退出了,接着登陆,又退出了,到底还做不做生意了。


这个案例中的问题,产生的根本原因是因为系统中存在着大量“有状态”的业务处理过程。

二、“有状态”和“无状态”

N.Wirth 曾经在它 1984 年出版的书中将程序的定义经典的概括为:程序=数据结构+算法。(这个概括也是这本书的书名)


这是一个很有意思的启发,受它的影响,z 哥认为程序做的事情本质就是“数据的移动和组合”,以此来达到我们所期望的结果。而如何移动、如何组合是由“算法”来定的,所以 z 哥延伸出一个新的定义:数据+算法=成果。


通过程序处理所得到的“成果”其实和你平时生活中完成的任何事情所得到的“成果”是一样的。任何一个“成果”都是你通过一系列的“行动”将最开始的“原料”进行加工、转化,最终得到你所期望的“成果”。



比如,你将常温的水,通过“倒入水壶”、“通电加热”等工作后变成了 100 度的水,就是这样一个过程。


正如烧水的例子,大多数时候得到一个“成果”往往需要好几道“行动”才能完成。



这个时候如果想降低这几道“行动”总的成本(如:时间)该怎么办呢?


自然就是提炼出反复要做的事情,让其只做一次。而这个事情在程序中,就是将一部分“数据”放到一个“暂存区”(一般就是本地内存),以提供给相关的“行动”共用。



但是如此一来,就导致了需要增加一道关系,以表示每一个“行动”与哪一个“暂存区”关联。因为在程序里,“行动”可能是“多线程”的。


这时,这个“行动”就变成“有状态”的了。



题外话:共用同一个“暂存区”的多个“行动”所处的环境经常被称作“上下文”。


我们再来深入聊聊“有状态”。


“暂存区”里存的是“数据”,所以可以理解为“有数据”就等价于“有状态”。


“数据”在程序中的作用范围分为“局部”和“全局”(对应局部变量和全局变量),因此“状态”其实也可以分为两种,一种是局部的“会话状态”,一种是全局的“资源状态”。


题外话:因为有些服务端不单单负责运算,还会提供其自身范围内的“数据”出去,这些“数据”属于服务端完整的一部分,被称作“资源”。所以,理论上资源可以被每个会话来使用,因此是全局的状态。


本文聊的“有状态”都指的是“会话状态”。


与“有状态”相反的是“无状态”,“无状态”意味着每次“加工”的所需的“原料”全部由外界提供,服务端内部不做任何的“暂存区”。并且请求可以提交到服务端的任意副本节点上,处理结果都是完全一样的。


有一类方法天生是“无状态”,就是负责表达移动和组合的“算法”。因为它的本质就是:


  1. 接收“原料”(入参)

  2. “加工”并返回“成果”(出参)

  3.  

  4. 为什么网上主流的观点都在说要将方法多做成“无状态”的呢?

  5.  

  6. 因为我们更习惯于编写“有状态”的代码,但是“有状态”不利于系统的易伸缩性和可维护性。

  7.  

  8. 在分布式系统中,“有状态”意味着一个用户的请求必须被提交到保存有其相关状态信息的服务器上,否则这些请求可能无法被理解,导致服务器端无法对用户请求进行自由调度(例如双 11 的时候临时加再多的机器都没用)。

  9.  

  10. 同时也导致了容错性不好,倘若保有用户信息的服务器宕机,那么该用户最近的所有交互操作将无法被透明地移送至备用服务器上,除非该服务器时刻与主服务器同步全部用户的状态信息。

  11.  

  12. 但是如果想获得更好的伸缩性,就需要尽量将“有状态”的处理机制改造成“无状态”的处理机制。

三、“无状态”化处理

将“有状态”的处理过程改造成“无状态”的,思路比较简单,内容不多。


首先,状态信息前置,丰富入参,将处理需要的数据尽可能都通过上游的客户端放到入参中传过来。



当然,这个方案的弊端也很明显:网络数据包的大小会更大一些。


另外,客户端与服务端的交互中如果涉及到多次交互,则需要来回传递后续服务端处理中所需的数据,以避免需要在服务端暂存。



(橙色请求,绿色响应)


这些改造的目的都是为了尽量少出现类似下面的代码。


func(){    return i++;}
复制代码


而是变成:


func(i){    return i+1;} 
复制代码


要更好的做好这个“无状态”化的工作,依赖于你在架构设计或者项目设计中的合理分层。


尽量将会话状态相关的处理上浮到最前面的层,因为只有最前面的层才与系统使用者接触,如此一来,其它的下层就可以将“无状态”作为一个普遍性的标准去做。


与此同时,由于会话状态集中在最前面的层,所以哪怕真的状态丢失了,重建状态的成本相对也小很多。


比如三层架构的话,保证 BLL 和 DAL 都不要有状态,代码的可维护性大大提高。


如果是分布式系统的话,保证那些被服务化的程序都不要有状态。除了能提高可维护性,也大大有利于做灰度发布、A/B 测试。


题外话:在这里,提到做分层的目的是为了说明,只有将 IO 密集型程序和 CPU 密集型程序分离,才是通往“无状态”真正的出路。一旦分离后,CPU 密集型的程序自然就是“无状态”了。


如此也能更好的做“弹性扩容”。因为常见的需要“弹性扩容”的场景一般指的就是 CPU 负荷过大的时候。


最后,如果前面的都不合适,可以将共享存储作为降级预案来运用,如远程缓存、数据库等。然后当状态丢失的时候可以从这些共享存储中恢复。


所以,最理想的状态存放点。要么在最前端,要么在最底层的存储层。


四、总结

任何事物都是有两面性的,正如前面提到的,我们并不是要所有的业务处理都改造成“无状态”,而只是挑其中的一部分。最终还是看“价值”,看“性价比”。


比如,将一个以“状态”为核心的即时聊天工具的所有处理过程都改造成“无状态”的,就有点得不偿失了。


2019-01-24 09:307544

评论 3 条评论

发布
用户头像
那像flink这样的有状态的流式计算,是不是就是 io密集和cpu密集没有分开呀
2019-09-30 22:29
回复
用户头像
写的很好,不知道什么时候能出下一期?
2019-04-16 21:18
回复
用户头像
学习了
2019-03-05 08:50
回复
没有更多了
  • 深入了解 Flutter 的状态管理机制(上)

    因此,本篇引入了一个 ModelBinding 类,通过继承 InheritedWidget 来实现子组件可以直接访问上级组件的状态,从而避免了状态参数的层层传递,也能清晰地了解状态管理的机制。

    2022-05-09

  • JUnit 中的设计模式(下)

    2022-09-10

  • 聊聊 Vuex 原理

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。如果你已经灵活运用,但是依然好奇它底层实现逻辑,不妨一探究竟。

    2022-10-10

  • 状态机的概念与设计

    一般情况下,状态触发器的数量是有限的,其状态数也是有限的,故称为有限状态机(Finite State Machine,简称为FSM)。状态机中所有触发器的时钟输入端被连接到一个公共时钟脉冲源上,其状态的转换是在同一时钟源的同一脉冲边沿同步进行的,所以它也被称作时

    2023-02-09

  • 05. 产品经理要时刻扪心自问的四个问题

    2023-10-17

  • React 源码分析 8- 状态更新的优先级机制

    这是我的剖析 React 源码的第二篇文章,如果你没有阅读过之前的文章,请务必先阅读一下 第一篇文章 中提到的一些注意事项,能帮助你更好地阅读源码。

    2022-12-12

  • 1. 状态与状态空间

    2023-09-26

  • StatePattern- 状态模式

    状态模式(State Pattern):又称为状态机模式(State Machine Pattern),是允许对象在内部状态发生改变的同时改变对象的行为,使得看起来像是修改了类一样,其核心就是给每一种状态绑定一种行为。

    2022-06-05

  • React 源码分析 8- 状态更新的优先级机制

    这是我的剖析 React 源码的第二篇文章,如果你没有阅读过之前的文章,请务必先阅读一下 第一篇文章 中提到的一些注意事项,能帮助你更好地阅读源码。

    2022-11-08

  • 聊聊 Vuex 原理

    Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。Vuex 是专门为 Vue.js 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。如果你已经灵活运用,但是依然好奇它底层实现逻辑,不妨一探究竟。

    2022-11-04

  • 数字经济的重要基石——数据安全

    数据安全是指通过采取必要措施,确保数据处于有效保护和合法利用的状态,以及具备保障持续安全状态的能力。

    2022-03-26

  • 课件资料

    2023-09-26

  • 17|应用状态管理(下):该用 React 组件状态还是 Redux?

    这节课,我们会把Redux与React结合起来使用,看看它能为React的状态管理带来什么好处,同时也要探讨什么时候该用Redux,什么时候用React内建的state,更或者,是否可以混用两种状态管理。

    2022-10-08

  • 接口调试时如何请求一个需要登录才能访问的接口

    在后台在开发、调试接口时,常常会遇到需要登陆才能请求的接口。比如:获取登陆用户的收藏列表,此时,我们就需要模拟登陆状态进行接口调试了。今天,我们讲解利用Apipost的环境变量,解决这种需要先登录再请求的接口依赖情况。ApiPost提供了2种方案

    2023-02-17

  • react 源码解析 12. 状态更新流程

    1.开篇介绍和面试题

    2021-12-15

  • 5. 动态规划总论:状态设计的要点和技巧

    2023-09-27

  • CSS 之选择器(二)

    我们还是进行上一篇的内容,继续我们的 CSS 选择器分类说明,今天要介绍的是我们的条件选择以及状态选择器,条件选择器,可能平时开发的时候接触的比较少,但是状态选择器,你肯定经常会遇到,尤其在表单的填写上,比如说:focus,:valid,接下来,就让我们

    2021-12-10

  • 了解 Session、LocatStorage、Cache-Control、ETag

    由于 HTTP 协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户,这个机制就是 Session. 典型的场景比如购物车,当你点击下单按钮时,由于 HTTP 协议无状态

    2022-06-14

  • react 源码解析 12. 状态更新流程

    1.开篇介绍和面试题

    2022-04-14

  • React-hooks 面试考察知识点汇总

    在组件之间复用状态逻辑很难

    2022-11-01

发现更多内容

智源千万级指令微调数据集Infinity-Instruct持续迭代,Llama3.1仅微调即可接近GPT-4

智源研究院

房地产行业具体怎么定义呢?需要堡垒机吗?

行云管家

网络安全 数据安全 堡垒机 房地产

Apache RocketMQ 中文社区全新升级!

阿里巴巴云原生

阿里云 云原生 Apache RocketMQ

基于LangChain手工测试用例转接口自动化测试生成工具

测吧(北京)科技有限公司

测试

京东电商自动化运营,4款RPA机器人免费用

八爪鱼采集器︱RPA机器人

RPA 自动化 电商 RPAxAI

华为云低代码AstroZero技巧教学1:表格的超链接赋能

华为云PaaS服务小智

低代码 华为云

lut调色预设怎么用?LUT预设导入fcpx/PR/AE/PS/LR/达芬奇 详细教程

Rose

lut调色预设 lut调色预设怎么安装

photoshop 运行弹窗This non-genuine Adobe app has been disabled 详细的解决方法

Rose

脱敏效率提升70%!城商行:嘉为蓝鲸日志中心助力保障数据安全与合规

嘉为蓝鲸

运维 日志 日志管理 银行业

英文版Premiere Pro怎么切换成中文?PR汉化包怎么安装

Rose

Premiere Pro 2024直装版 Premiere Pro中文版 PR下载安装

加密创投周期进化论:未来或黯淡,但流动性是那道光

区块链软件开发推广运营

dapp开发 区块链开发 链游开发 NFT开发 公链开发

基于LangChain手工测试用例转接口自动化测试生成工具

测试人

软件测试

高效!实用!还免费!八爪鱼RPA应用市场上线啦!

八爪鱼采集器︱RPA机器人

RPA 自动化 RPAxAI

2024福州等保测评机构名单大汇总

行云管家

等保 等保测评 福州

Final Cut Pro教程:fcpx跟踪功能如何添加马赛克?

Rose

Lightroom Classic教程:修复画笔(污点去除)工具的使用

Rose

Lightroom Classic教程 lr修复画笔工具

828 B2B企业节·深圳站--智慧交互:AI与大模型的融合创新研讨会圆满举办

最新动态

A Better Finder Rename 12 for Mac(苹果电脑批量重命名工具)

Mac相关知识分享

Mac软件

AirServer 7 mac激活版:macOS专业的投屏工具

Rose

AirServer 7 mac激活版 mac投屏软件 airserver投屏

磁盘管理软件Tuxera NTFS for Mac破解资源及使用教程

Rose

Tuxera NTFS Mac2022 Tuxera NTFS教程 磁盘格式化 Mac NFFS

区块链Dapp开发:质押挖矿的各模式开发部署搭建

V\TG【ch3nguang】

区块链开发 质押挖矿系统开发

API 接口性能优化管理

Noah

PS画画工具推荐:让画面一键发光的 PS 插件如何使用

Rose

【灾备应急管理】《2023年金融机构业务连续性管理能力建设调研报告》解读

嘉为蓝鲸

灾备建设 金融业 业务连续性

区块链游戏开发NFT游戏开发艺术品交易盲盒系统

V\TG【ch3nguang】

花见Live Wallpaper & Themes 4K Pro for mac(4k视频壁纸)

Mac相关知识分享

“AI+Security”系列第2期(三):面向LLM(大语言模型)的漏洞挖掘与对齐防御研究

云起无垠

企业该怎么适应数字化转型?

优秀

数字化转型

如何快速查看 Mac 的温度?

Rose

量化交易的基石:ExchangeSdk

Silently9527

比特币 币安智能链 量化交易

回顾加密风险投资15年演变:步履维艰,但总体向上

区块链软件开发推广运营

dapp开发 区块链开发 链游开发 NFT开发 公链开发

分布式系统关注点——“无状态”详解_后端_张帆_InfoQ精选文章