news 2026/5/8 19:24:02

无状态与有状态服务大揭秘:定义、场景、架构对比及有状态服务重构方法

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
无状态与有状态服务大揭秘:定义、场景、架构对比及有状态服务重构方法

无状态与有状态服务大揭秘:定义、场景、架构对比及有状态服务重构方法

本文内容较多,分为如下部分:无状态服务和有状态服务定义、无状态服务应用场景、有状态服务应用场景、有无状态俩种服务的架构质量对比、实现有状态服务的挑战、有状态服务重构成无状态服务。

警告:任何情况下都优先考虑使用无状态服务,及时你阅读本文,包括以后写的有状态服务实现模式后。

在分布式系统里,节点服务包含了`业务处理`和`数据`俩部分。如果数据是从持久化系统加载,则认为此节点是有状态的;如果数据常驻于节点内,业务逻辑是从外部加载进来的,则认为是有状态节点。

绝大多数系统都是无状态服务,服务不需要在服务本地(JVM)记录同一个客户端(如用户,设备,或者其他作为客户端的服务等)请求的历史状态或者记录客户端的信息,服务需要的这些数据将从数据库或者Redis,MongDB加载。这些服务类似如下:登录服务,服务节点根据请求用户名,从数据库查询用户名和HASH后的密码,然后判断请求的密码是否与数据库查询的密码一致;搜索服务 ,服务节点会把查询条件转为ElasticSearch查询JSON,请求Elastic Search查询结果;电商中库存查询,服务节点会根据商品SKU以及查询所在的地区,查询存放在Redis的库存信息。同时库存服务节点也会请求商品查询服务查询商品的名称和价格等信息;物联网中查询家庭设备的状态,服务节点会查询俩个Redis,一个是缓存设备信息的Redis,一个设备在离线状态的Redis。

无状态服务的技术实现非常成熟,如果你的服务是无状态,仅仅需要增加节点既可实现系统高可用和高性能。 如下图,代理服务采用轮询(Round Robin)或则随机,对于客户端C,每个服务节点都能提供服务。如果需要扩容,简单增加服务节点4即可。

需要注意的是,随着流量增加,而服务节点增加,导致代理服务和数据库本身可能是高可用高性能的瓶颈。因此代理服务和数据库节点也应该支持扩展节点。

无状态服务的主要优点:

优点说明
实现简单像编写CURD代码那样简单
扩容简单增加节点即可,代理服务可以使用轮询,随机等路由技术实现。

与无状态服务对应的是有状态服务,要求服务端记录同一个客户端的交互历史数据和状态数据,有状态服务通常从外部加载执逻辑而不是数据。比如:用户前端流程表单在最终提交前保留在服务端的临时表单数据;用户登录后的会话信息放在Session,Session信息存放在JMV内存里;物联网的接入网关,需要记录长链接到此网关的设备的版本信息。网关服务有可能加载规则脚本,规则引擎会根据设备上报的数据来执行特定的业务逻辑;游戏服务,一群用户会被路由到特定的地图服务器上协作完成游戏;通过互联网协作编写一份文档;导航系统,用户的信息和旅程信息都在一个服务器上。实时导航信息也在这一台服务器上更新;Zookeeper内存中保持的有ZTree数据结构,它通过ZAB协议保持所有节点数据都一致;Redis本身也是有个有状态服务节点,它支持在内存存储各种数据结构以及加载执行脚本。它通过从节点来实现高可用。

有状态需要客户端始终连接到同一个服务节点(持久化连接),需要客户端或者代理服务采取的路由策略保证同一个客户任何请求都在同一个节点执行,比如来自同一个IP的用户。

有状态服务的主要优点如下:

优点说明
高性能主要避免了从数据库加载数据的延迟;也避免了从持久化系统反复加载数据,比如节点1加载数据执行业务逻辑完毕后,当请求路由到节点2的时候,又会在节点2再次加载同样数据。
任意状态数据结构不再需要持久化系统保存状态数据,其状态不限制于JSON,表数据结构。
CAP分布式常见的AP能得到满足外,由于数据在同一个节点,其C也能满足。需要注意,但是如果主节点宕机(或者客户端认为C宕机路由到从节点),从节点接管,则C不成立。
避免使用性能不佳的数据库无状态服务的扩容,也会导致其用的数据库节点扩容。无状态节点因为不需要数据库,则省去了数据库的使用成本,以及其导致的性能瓶颈。

有状态服务不难实现,但要达成高可用目标,则难得多。 下图是一个通常有状态服务高可用的部署架构。

这个架构里,有非常多的技术挑战性,列表如下。 这些挑战是分布式系统高可用的深水区,后面章节简述如何攻克这些挑战。

难点说明举例
持久连接代理服务采用何种策略让客户端保持持久连接到同一个节点,包括客户端的每次请求,客户端重启,服务节点重启,以及扩容缩容后通知客户端重连新节点。如果没有代理服务,则需要客户端实现持久化连接设备总是链接到同一个网关,游戏玩家总是链接到同一个区域服务器
复制为节点增加一个从节点,数据从主节点备份到从节点。当节点宕机,从节点接替主节点工作。从节点也可收接收只读服务请求,缓解主节点负载Redis主从数据复制,Zk的主从数据复制
读写一致如果从节点提供读服务,如何保证客户端读到最新写到此分区的数据。阿里云Redis可以配置只有主分片提供服务以避免读写不一致。
分区把有状态服务分成多个节点,解决有状态服务的存储瓶颈和访问性能。物联网网关集群,Redis数据分片,数据库分区,Kafka分区等
分区再平衡在扩容时候,如果不差钱,每个分区都再次拆分2个分区,此分区数据只需要复制到俩分区。这种扩容成本极高但数据均匀。如果扩容时候是增加少量节点。则因为持久化连接缘故,新增节点负载长期都较低。扩容效果不能立即显现出来。阿里云的Redis扩容采用的是成倍增长,支持4,8,16....2048个分片。不支持增加少量分区
分布式共识数据备份给多个节点,当主节点挂掉,采用那个节点的数据为主节点。另外,新当选的的主节点需要继续同步数据到从节点ZK通过ZAB实现分布式共识
集群管理需要感知整个集群的节点状态,其主从的工作状态。代理服务需要获取这些数据以实现路由物联网设备的主网关,Redis集群的代理
业务逻辑加载如果有状态服务的业务逻辑通过外部加载实现,如果管理这些业务逻辑物联网的规则链,通过配置其规则节点和执行逻辑实现设备在离线,属性上报等执行逻辑。Reids作为有状态节点,可以加载和执行Lua脚本

基于无状态服务和有状态服务各自的优缺点,下表总结了俩种服务的架构质量:

架构特点关注点无状态服务有状态服务
高可用API网关API网关可以实现各种负载均衡策略。如随机,轮询,负载API网关实现较为复杂,需要识别客户端,保证每次路由到同一个有状态服务,依据信息可能是客户端IP和端口,也可能是HTTP头中包含的客户ID
故障恢复重启服务即可恢复故障有状态服务重启后,状态丢失。需要重新建立这些状态,如设备的版本信息,用户的购物车。因此故障恢复较慢这些状态需要从持久化系统加载,或者依赖客户端重置状态。
故障容错无状态服务支持重试,当服务宕机,API网关可以将请求路由到另外其他服务。不存在单机故障有状态服务宕机,状态丢失。需要在其他节点重建状态,比如有状态服务保持的有用户登录信息,当宕机后,用户再访问其他服务前,需要再次登录。
高性能启动性能无状态服务不需要加载状态,因此重启后访问较快。有状态服务,服务重启后,需要初始化端状态,访问性能第一次较慢。重启可能造成服务响应延迟
访问性能无状态服务通常将状态维护在Redis中,性能稍微慢一些,但考虑到Redis这些延迟都是毫秒级的,整体性能很高。如果状态数据维护在传统数据,则延迟较高有状态服务在JVM内存在保持状态,访问速度更快。如游戏地图,所有玩家都在一个游戏地图(JVM)里有状态服务适合游戏,导航等场景。
可修改易于修改通常无状态服务,不需要在JVM里维护状态,实现更简单,易于修改。在JVM里维护的状态,数据结构私有,难以修改,另外涉及到并发访问,编写代码容易出错
热发布无状态服务可以采用任何热发布技术,而没有风险有状态服务,需要把状态数据迁移到热发布后的结构,难度较大
可伸缩性节点扩容集群环境,无状态服务可以任意增加或者减少,无状态服务扩容后,API网关可以通过负载均衡策略,让负载少的这些扩容节点能很快达到满负荷容易造成单点过载。有状态服务扩容后,由于持久化链接需要,至少少量请求能立即路由到新的节点。扩容后需要较长时间新老节点的容量才能达到一个均衡值。

既然无状态服务有如此多的优点,除非有高性能要求,架构中应该优先使用无状态服务,如果是有状态的服务,需要改成无状态服务,这里有4个办法:有状态服务的状态数据存放在Redis等更为可靠的存储介质。比如用户Session,订单,购物车等信息存放到redis,一些长期存在的数据存放到数据库。 一些高可用基础设施的改进采用了此方案,比如Kafka新一代方案[Diskless Kafka](https://www.toutiao.com/article/7580613850573636096/?app=news_article×tamp=1766026761&use_new_style=1&req_id=202512181059202FECEDBD55AB8CE8CEF8&group_id=7580613850573636096&req_id_new=202512181059202FECEDBD55AB8CE8CEF8&chn_id=-3&share_did=MS4wLjACAAAAVfSFXxfg6-hPXBlA91hyWI_ffD_1qQBvN0-ctQ0FziQ-e9QwR5XZSLS-3frGcjyh&share_uid=MS4wLjABAAAAmteeVOpFKtElQwG-v4vK9j0tOsx0sCxFUFgS5VUJwUo&upstream_biz=harmony_share_os&origin=Wechat&source=m_redirect&wid=1766300898062)的实现AutoMQ ,消息本地存储变成存储到对象存储服务里。 Nacos将配置数据放到Mysql数据库中;服务端的状态每次都回传给客户端,客户端下次调用携带这些状态,比如JWT,Cookie;有状态服务把有状态部分单独隔离出来,把其他部分放在无状态服务里;使用Zookeeper,数据库等强一致工具来实现投票,元数据管理,二阶段提交等,而无需自己实现。

下图是Spring Boot提供的Session实现方式,代替传统的保存会话到内存,Spring Boot 配置spring.session.store-type:

spring.session.store-type=Redis

配置后,存在内存中的的用户会话数据将序列化后存放在redis中。

其他配置还允许使用数据库、Hazelcast等存储系统。需要注意,必须确保存储系统的高性能和高可用。在我的一个项目里,用此方案把有状态服务改成无状态服务,额外引入了一个512分片,容量是1024G的Redis集群以避免系统性能问题。

另外一种把有状态服务改成无状态服务的方法是服务器每次把状态回传给客户端。适合用户状态数据较少情况。

交互过程如下:服务在接受客户端请求后,将数据放回到Cookie中,如加密的用户的信息,或者订单信息;客户端下次请求,服务端从Cookie中取出的状态数据,处理请求后新的状态数据再次保存到Cookie中。

在还没有无纸办公时代,我在派出所办理业务的时候,按照要求需要跑多次派出所和其他相关单位,派出所工作人员会把需要跑的单位记录在一张纸上,每次交互后的结果和剩下需要办的事情都有记录,再次去派出所,其他工作人员即使没有给我办理过业务,也会让我拿出这张纸查看,以了解我办理的进度。

第三种是在设计有状态服务时候,拆分有状态服务。这样好处是让大部分功能保持在无状态服务里。

第四种方法与第三种类似,使用zookeeper来管理有状态,相比于自己实现有状态服务,zookeeper/etcd这些基础中间件更为可靠。

有状态服务的高可用涉技术实现包括大量内容,本书将用后续一节内容说明实现有状态服务的高可用有哪些模式。

再次警告:有状态服务高可用实现难度较大。类似你正在实现一个Redis,Kafka这样的中间件。你需要承担为了性能引入的复杂性。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/8 19:22:36

Python分布式爬虫框架ClawPlay:从架构设计到生产部署全解析

1. 项目概述:从零到一,构建一个高效、可扩展的爬虫与数据处理平台最近在整理过往项目时,我翻出了一个自己曾经深度参与并持续维护的爬虫框架项目,它的名字叫slicenferqin/clawplay。这个名字听起来可能有点“玩票”性质&#xff0…

作者头像 李华
网站建设 2026/5/8 19:21:40

手机充电电路硬件保护设计与看门狗应用

1. 手机充电电路的安全隐患与保护需求在移动设备设计中,电池充电管理一直是硬件工程师面临的核心挑战之一。传统手机充电架构中,基带处理器通过PWM信号控制p沟道MOSFET开关,直接连接充电器输入与电池正极。这种设计虽然简单高效,但…

作者头像 李华
网站建设 2026/5/8 19:20:48

bumpalo内存管理深度剖析:从源码理解bump分配原理

bumpalo内存管理深度剖析:从源码理解bump分配原理 【免费下载链接】bumpalo A fast bump allocation arena for Rust 项目地址: https://gitcode.com/gh_mirrors/bu/bumpalo bumpalo是一个为Rust设计的快速bump分配内存池,它通过独特的内存管理策…

作者头像 李华
网站建设 2026/5/8 19:20:34

终极指南:优化Go语言CGO编译参数,提升构建效率的7个实用技巧

终极指南:优化Go语言CGO编译参数,提升构建效率的7个实用技巧 【免费下载链接】advanced-go-programming-book :books: 《Go语言高级编程》开源图书,涵盖CGO、Go汇编语言、RPC实现、Protobuf插件实现、Web框架实现、分布式系统等高阶主题(完稿…

作者头像 李华
网站建设 2026/5/8 19:17:52

四叶草拼音词库构建指南:从360万词库到智能拼音处理

四叶草拼音词库构建指南:从360万词库到智能拼音处理 【免费下载链接】rime-cloverpinyin 🍀️四叶草拼音输入方案,做最好用的基于rime开源的简体拼音输入方案! 项目地址: https://gitcode.com/gh_mirrors/ri/rime-cloverpinyin …

作者头像 李华
网站建设 2026/5/8 19:13:32

PC音频系统爆裂声与咔嗒声的硬件解决方案

1. PC音频系统中的爆裂声与咔嗒声问题解析 作为一名在音频硬件设计领域工作多年的工程师,我经常遇到PC音频系统中出现的爆裂声(Pop)和咔嗒声(Click)问题。这些恼人的噪声不仅影响用户体验,长期积累还可能对…

作者头像 李华