写点什么

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

  • 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:307601

评论 3 条评论

发布
用户头像
那像flink这样的有状态的流式计算,是不是就是 io密集和cpu密集没有分开呀
2019-09-30 22:29
回复
用户头像
写的很好,不知道什么时候能出下一期?
2019-04-16 21:18
回复
用户头像
学习了
2019-03-05 08:50
回复
没有更多了
  • 5. 动态规划总论:状态设计的要点和技巧

    2023-09-27

  • CSS 之选择器(二)

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

    2021-12-10

  • 深入了解 Flutter 的状态管理机制(上)

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

    2022-05-09

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

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

    2022-03-26

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

    1.开篇介绍和面试题

    2022-04-14

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

    2023-10-17

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

    1.开篇介绍和面试题

    2021-12-15

  • 聊聊 Vuex 原理

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

    2022-11-04

  • StatePattern- 状态模式

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

    2022-06-05

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

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

    2022-11-08

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

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

    2022-10-08

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

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

    2022-12-12

  • 1. 状态与状态空间

    2023-09-26

  • 课件资料

  • 状态机的概念与设计

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

    2023-02-09

  • JUnit 中的设计模式(下)

    2022-09-10

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

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

    2023-02-17

  • 聊聊 Vuex 原理

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

    2022-10-10

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

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

    2022-06-14

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

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

    2022-11-01

发现更多内容

还有谁不知道CRM系统可以为企业做这些?

低代码小观

CRM 客户关系管理 CRM系统 客户关系管理系统 企业管理软件

node爬虫爬取小说章节

空城机

爬虫 Node 5月月更

百问百答第37期:如何一次性贯穿前后请求,调用链告诉你答案

博睿数据

调用链 博睿数据 IT运维

AI驱动音乐创新,网易数帆X云音乐刷新MIREX世界纪录

网易数帆

人工智能 AI 语音识别 歌词识别 预练习

RGB色彩空间

Loken

音视频 5月月更

云图说|DDS读写两步走,带您领略只读节点的风采

华为云开发者联盟

数据库 华为云 读写分离 DDS

OpenHarmony布道师招募正式启动,打造个人技术影响力的机会来了!

科技汇

升级HarmonyOS 2最新版本,出门亮健康码快人一步!

科技汇

大咖说 X 智篆商业|未来五年:消费增长的“两大来源”与“四个方面”

大咖说

阿里云 存量时代 智篆商业

融云参编,业界首个办公即时通信软件安全标准重磅发布!

融云 RongCloud

WordPress 固定链接设置

海拥(haiyong.site)

5月月更

加速虚拟与现实交互,2022视觉计算私享会邀请你一起沉浸体验

阿里云弹性计算

vr 虚拟现实 元宇宙 视觉计算

连续3年实力登榜!EMQ映云科技再度跻身“2022中国边缘计算企业20强”

EMQ映云科技

物联网 IoT 边缘计算 emq 5月月更

豆瓣评分8.5,详细讲解Python基础知识和应用的百科全书来了!

图灵教育

Python 程序员 计算机

主流开源分布式图计算框架 Benchmark

NebulaGraph

图计算 分布式图数据库

如何写出GC更优的代码,以达到提升代码性能的目的

非凸科技

性能 编程语言 垃圾回收 GC 吞吐率

易周金融观点 | 支付机构入局数字藏品;Q1手机银行交易超150万亿

易观分析

金融

web前端培训React性能优化总结

@零度

前端开发 React

OpenHarmony兼容性平台更新上线

OpenHarmony开发者

OpenHarmony 兼容性平台

黎明前的至暗时刻,旅企是该坚守还是放弃?

易观分析

旅游业

墨天轮访谈 | 百度云邱学达:GaiaDB如何解决云上场景的业务需求?

墨天轮

数据库 百度云 国产数据库

java培训Redis数据结构面试分享

@零度

redis JAVA开发

CWE 4.7中的新视图:工业控制系统的安全漏洞类别

华为云开发者联盟

安全漏洞 cwe 软件安全 CWE 4.7 工业控制系统

Connection reset

领创集团Advance Intelligence Group

Connection reset

【Linux深潜】详解Linux系统自身安全调优配置

沃趣科技

Linux

跟我学Python图像处理丨掌握4种图像平滑算法

华为云开发者联盟

Python OpenCV 图像属性 兴趣ROI区域 图像通道

OpenHarmony 3GPP协议开发深度剖析——一文读懂RIL

OpenHarmony开发者

OpenHarmony RIL

架构实战营 第 6 期 模块五课后作业

火钳刘明

架构实战营 「架构实战营」

OpenMLDB官网升级,神秘贡献者地图带你快速进阶!

第四范式开发者社区

人工智能 机器学习 数据库 开源 特征

做本让客户念念不忘的产品手册

小炮

产品手册

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