如果这是第二次看到我的文章,欢迎文末扫码订阅我的个人公众号(跨界架构师)哟~
本文长度为2728字,建议阅读8分钟。
坚持原创,每一篇都是用心之作~
前面聊完的2个章节「数据一致性」和「高可用」其实本质是一个通过提升复杂度让整体更完善的方式。
接下去我们开始聊一些让系统更简单,更容易维护的东西——「易伸缩」,首当其冲的第一篇文章就是「stateless」,也叫「无状态」。
z哥带你先来认识一下「状态」是什么。
一、初识「状态」
之前在「负载均衡」的第四篇(分布式系统关注点——做了「负载均衡」就可以随便加机器了吗?)中提到过一个例子,我们再翻出来一下。
开发Z哥对运维Y弟喊:“Y弟,现在系统好卡,刚上了一波活动,赶紧帮我加几台机器上去顶一下。”
Y弟回复说:“没问题,分分钟搞定”。
然后就发现数据库的压力迅速上升,DBA就吼了:“Z哥,你丫的搞什么呢?数据库要被你弄垮了”。
然后客服那边接框也爆炸了,越来越多的用户说刚登陆后没多久,操作着就退出了,接着登陆,又退出了,到底还做不做生意了。
这个案例中的问题,产生的根本原因是因为系统中存在着大量「有状态」的业务处理过程。
二、「有状态」和「无状态」
N.Wirth曾经在它1984年出版的书中将程序的定义经典的概括为:程序=数据结构+算法。(这个概括也是这本书的书名)
这是一个很有意思的启发,受它的影响,z哥认为程序做的事情本质就是“数据的移动和组合”,以此来达到我们所期望的结果。而如何移动、如何组合是由“算法”来定的,所以z哥延伸出一个新的定义:数据+算法=成果。
通过程序处理所得到的“成果”其实和你平时生活中完成的任何事情所得到的“成果”是一样的。任何一个“成果”都是你通过一系列的“行动”将最开始的“原料”进行加工、转化,最终得到你所期望的“成果”。
比如,你将常温的水,通过“倒入水壶”、“通电加热”等工作后变成了100度的水,就是这样一个过程。
正如烧水的例子,大多数时候得到一个“成果”往往需要好几道“行动”才能完成。
这个时候如果想降低这几道“行动”总的成本(如:时间)该怎么办呢?
自然就是提炼出反复要做的事情,让其只做一次。而这个事情在程序中,就是将一部分“数据”放到一个「暂存区」(一般就是本地内存),以提供给相关的“行动”共用。
但是如此一来,就导致了需要增加一道关系,以表示每一个“行动”与哪一个「暂存区」关联。因为在程序里,“行动”可能是「多线程」的。
这时,这个“行动”就变成「有状态」的了。
题外话:共用同一个「暂存区」的多个“行动”所处的环境经常被称作「上下文」。
我们再来深入聊聊「有状态」。
「暂存区」里存的是「数据」,所以可以理解为“有数据”就等价于“有状态”。
「数据」在程序中的作用范围分为「局部」和「全局」(对应局部变量和全局变量),因此「状态」其实也可以分为两种,一种是局部的「会话状态」,一种是全局的「资源状态」。
题外话:因为有些服务端不单单负责运算,还会提供其自身范围内的「数据」出去,这些「数据」属于服务端完整的一部分,被称作「资源」。所以,理论上「资源」可以被每个「会话」来使用,因此是全局的状态。
本文聊的「有状态」都指的是「会话状态」。
与「有状态」相反的是「无状态」,「无状态」意味着每次“加工”的所需的“原料”全部由外界提供,服务端内部不做任何的「暂存区」。并且请求可以提交到服务端的任意副本节点上,处理结果都是完全一样的。
有一类方法天生是「无状态」,就是负责表达移动和组合的“算法”。因为它的本质就是:
-
接收“原料”(入参)
-
“加工”并返回“成果”(出参)
为什么网上主流的观点都在说要将方法多做成「无状态」的呢?
因为我们更习惯于编写「有状态」的代码,但是「有状态」不利于系统的易伸缩性和可维护性。
在分布式系统中,「有状态」意味着一个用户的请求必须被提交到保存有其相关状态信息的服务器上,否则这些请求可能无法被理解,导致服务器端无法对用户请求进行自由调度(例如双11的时候临时加再多的机器都没用)。
同时也导致了容错性不好,倘若保有用户信息的服务器宕机,那么该用户最近的所有交互操作将无法被透明地移送至备用服务器上,除非该服务器时刻与主服务器同步全部用户的状态信息。
这两个问题在负载均衡的第四篇(分布式系统关注点——做了「负载均衡」就可以随便加机器了吗?)中也有提到。
但是如果想获得更好的伸缩性,就需要尽量将「有状态」的处理机制改造成「无状态」的处理机制。
三、「无状态」化处理
将「有状态」的处理过程改造成「无状态」的,思路比较简单,内容不多。
首先,状态信息前置,丰富入参,将处理需要的数据尽可能都通过上游的客户端放到入参中传过来。
当然,这个方案的弊端也很明显:网络数据包的大小会更大一些。
另外,客户端与服务端的交互中如果涉及到多次交互,则需要来回传递后续服务端处理中所需的数据,以避免需要在服务端暂存。
▲橙色请求,绿色响应
这些改造的目的都是为了尽量少出现类似下面的代码。
func(){
return i++;
}
而是变成:
func(i){
return i+1;
}
要更好的做好这个「无状态」化的工作,依赖于你在架构设计或者项目设计中的合理分层。
尽量将会话状态相关的处理上浮到最前面的层,因为只有最前面的层才与系统使用者接触,如此一来,其它的下层就可以将「无状态」作为一个普遍性的标准去做。
与此同时,由于会话状态集中在最前面的层,所以哪怕真的状态丢失了,重建状态的成本相对也小很多。
比如三层架构的话,保证BLL和DAL都不要有状态,代码的可维护性大大提高。
如果是分布式系统的话,保证那些被服务化的程序都不要有状态。除了能提高可维护性,也大大有利于做灰度发布、A/B测试。
题外话:在这里,提到做分层的目的是为了说明,只有将IO密集型程序和CPU密集型程序分离,才是通往「无状态」真正的出路。一旦分离后,CPU密集型的程序自然就是「无状态」了。
如此也能更好的做「弹性扩容」。因为常见的需要「弹性扩容」的场景一般指的就是CPU负荷过大的时候。
最后,如果前面的都不合适,可以将共享存储作为降级预案来运用,如远程缓存、数据库等。然后当状态丢失的时候可以从这些共享存储中恢复。
所以,最理想的状态存放点。要么在最前端,要么在最底层的存储层。
四、总结
任何事物都是有两面性的,正如前面提到的,我们并不是要所有的业务处理都改造成「无状态」,而只是挑其中的一部分。最终还是看“价值”,看“性价比”。
比如,将一个以“状态”为核心的即时聊天工具的所有处理过程都改造成「无状态」的,就有点得不偿失了。
相关文章:
作者:Zachary
出处:https://www.cnblogs.com/Zachary-Fan/p/stateless.html
如果你喜欢这篇文章,可以点一下右下角的「推荐」。
这样可以给我一点反馈。: )
谢谢你的举手之劳。
▶关于作者:张帆(Zachary,个人微信号:Zachary-ZF)。坚持用心打磨每一篇高质量原创。欢迎扫描下方的二维码~。
定期发表原创内容:架构设计丨分布式系统丨产品丨运营丨一些思考。
如果你是初级程序员,想提升但不知道如何下手。又或者做程序员多年,陷入了一些瓶颈想拓宽一下视野。欢迎关注我的公众号「跨界架构师」,回复「技术」,送你一份我长期收集和整理的思维导图。
如果你是运营,面对不断变化的市场束手无策。又或者想了解主流的运营策略,以丰富自己的“仓库”。欢迎关注我的公众号「跨界架构师」,回复「运营」,送你一份我长期收集和整理的思维导图。
相关推荐
"深入理解InfluxDB——时序数据库详解与实践" 时序数据库的重要性 时序数据库(Time Series Database,TSDB)专门用于存储和管理时间序列数据,如温度传感器、股票交易数据、电力系统负荷等。它具有两个关键特性:...
该演讲主要围绕着Go语言在构建高并发分布式系统中的实践展开,通过具体的案例——360消息推送系统——来探讨Go语言在这一领域的应用。 #### 核心知识点概述 1. **Go语言的优势** - 开发体验良好 - 在一定量级下...
### 分布式数据库技术知识点详解 #### 一、概述 分布式数据库系统是一种跨越多个地理位置的数据库,通过网络连接起来,以便实现数据的集中管理和分散存储。这类系统在提高数据访问速度、增强系统可靠性和可扩展性...
5. **MVC架构**:尽管这里没有明确提及MVC(模型-视图-控制器)模式,但在ASP.NET中,MVC框架是一种常见的开发模式,它鼓励分离关注点,提高代码的可测试性和可维护性。 6. **ADO.NET**:作为.NET Framework的一...
"RotondeforBeakerBrowser建于在BeakerDat之上的分布式社交网络" 这个标题揭示了我们讨论的核心技术——Rotonde,它是一个为Beaker浏览器构建的分布式社交网络应用。Beaker Dat是基础架构的一部分,提供数据存储和...
Web Forms允许开发者使用事件驱动的控件模型来构建页面,而MVC模式则强调分离关注点,提高了可测试性和灵活性。 3. **C#与VB.NET编程**:ASP.NET支持两种主要的编程语言,C#和VB.NET,它们都是.NET Framework的一...
《Spring详解——Java全栈开发的关键》 Spring框架是Java企业级应用开发的基石,它以其灵活、高效和模块化的特性赢得了广大开发者的一致好评。本篇将深入探讨Spring的核心概念,包括IoC(Inversion of Control)...
物流信息系统中分布式工作流模型设计与软件实现是一个深入探讨如何运用现代信息技术优化物流管理流程的课题。该主题聚焦于利用分布式工作流模型提高物流效率,通过自动化订货、验证及配送等业务流程,旨在构建一个...
### Hadoop分布式文件系统(HDFS)运行测试知识点详解 #### 实验背景与目的 本次实验旨在通过对Hadoop分布式文件系统(HDFS)进行运行测试,深入理解并掌握Hadoop及其核心组件之一——HDFS的基本原理与操作方法。随着...
在分布式系统中,次序等价是一个重要的概念,它涉及到不同数据结构或算法中的元素之间的相对位置关系。具体到本题中,我们需要证明环Rrev中划分出的长度为j(j为2的幂)的连续片段是否具有次序等价性。 **知识点2:...
《diffusion技术详解——探索分布式系统中的信息扩散》 在信息技术日新月异的今天,分布式系统的概念已经深入人心。而“diffusion”一词,在IT领域中常常与数据传播、消息传递或者分布式计算相关联。本文将围绕...
- **DevOps要素**:可运维性、运维成本、无状态设计、标准化和自动化等。 ##### 2. 运维思维的转变 - **测试思维**:重视系统的稳定性和可靠性。 - **安全思维**:加强安全防护措施,保障容器的安全运行。 #### ...
#### 三、关键技术点详解 ##### 1. 微服务平台治理之道 - **业务垂直解耦**:通过将业务逻辑按照功能划分成不同的微服务,确保各个服务之间低耦合,减少相互依赖。 - **服务互不干涉**:确保每个微服务只关注自己的...
而ASP.NET MVC则是另一种轻量级、更灵活的架构,鼓励分离关注点。 5. **ADO.NET与数据库交互**:SQL For .Net2.0暗示了程序与数据库的交互,ADO.NET是.NET Framework中用于访问数据库的组件,包括DataSet、...
在过去,开发者的主要关注点在于如何部署和托管应用程序,这通常涉及到购买具有固定容量的服务器以满足预期的应用峰值需求,并安装及维护整个支撑应用的软件基础设施。这种模式下的服务器资源往往在非高峰时段被严重...
【描述】:在“点”这个项目中,我们探讨的是分布式系统项目的后续发展。这个阶段的目标是创建一个Android应用程序,能够流畅地播放音乐。该应用的设计与之前分布式系统存储库中的代码紧密集成,旨在展示如何在...
该方法通过使用多个并行视图来分别解决不同利益相关者(例如最终用户、开发者、系统工程师、项目经理等)的关注点,并分别处理功能性需求和非功能性需求。 **五种主要视图:** 1. **逻辑视图**(Logical View): ...
**核心知识点详解:** 1. **远程过程调用(RPC)**:RPC是一种进程间通信方法,允许一个程序调用另一个不在同一台计算机上的程序。zerorpc就是这样的一个实现,它隐藏了网络通信的复杂性,让开发者可以像调用本地...
1. Hadoop概述:Hadoop是Apache软件基金会的一个开源项目,基于Java实现,其核心包括两个主要组件——HDFS(Hadoop Distributed File System)和MapReduce。HDFS为分布式存储提供高容错性和高吞吐量,而MapReduce则...