45 | 弹力设计:服务的状态
陈皓
该思维导图由 AI 生成,仅供参考
你好,我是陈皓,网名左耳朵耗子。
之前在我们讲的幂等设计中,为了过滤掉已经处理过的请求,其中需要保存处理过的状态,为了把服务做成无状态的,我们引入了第三方的存储。而这一篇中,我们来聊聊服务的状态这个话题。我认为,只有清楚地了解了状态这个事,我们才有可能设计出更好或是更有弹力的系统架构。
所谓“状态”,就是为了保留程序的一些数据或是上下文。比如之前幂等性设计中所说的需要保留每一次请求的状态,或是像用户登录时的 Session,我们需要这个 Session 来判断这个请求的合法性,还有一个业务流程中需要让多个服务组合起来形成一个业务逻辑的运行上下文 Context。这些都是所谓的状态。
我们的代码中基本上到处都是这样的状态。
无状态的服务 Stateless
一直以来,无状态的服务都被当作分布式服务设计的最佳实践和铁律。因为无状态的服务对于扩展性和运维实在是太方便了。没有状态的服务,可以随意地增加和减少节点,同样可以随意地搬迁。而且,无状态的服务可以大幅度降低代码的复杂度以及 Bug 数,因为没有状态,所以也没有明显的“副作用”。
基本上来说,无状态的服务和“函数式编程”的思维方式如出一辙。在函数式编程中,一个铁律是,函数是无状态的。换句话说,函数是 immutable 不变的,所有的函数只描述其逻辑和算法,根本不保存数据,也不会修改输入的数据,而是把计算好的结果返回出去,哪怕要把输入的数据重新拷贝一份并只做少量的修改(关于函数式编程可以参看我在 CoolShell 上的文章《函数式编程》)。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
本文深入探讨了分布式系统设计模式中关于无状态服务和有状态服务的设计模式,以及它们在分布式系统中的应用和优劣势。文章首先介绍了无状态服务的优点,即便于扩展性和运维,但也指出了将状态保存到第三方存储中增加了网络开销的问题。相比之下,有状态服务具有数据本地化、更高的可用性和更强的一致性等优势,但也面临负载和数据不均匀的问题。作者还提到了一些有状态服务的自动化伸缩的真实案例,如Facebook的Scuba、Uber的Ringpop和微软的Orleans。总的来说,无状态服务和有状态服务各有优劣,需要根据具体情况进行选择和权衡。 此外,文章还涉及了有状态服务的容错设计,包括数据在运行时的复制、一致性问题、分布式文件系统的重要性等内容。作者强调了使用分布式文件系统对于调度有状态服务的关键性,并总结了无状态服务和有状态服务的特点及其在分布式系统中的应用技术。 总的来说,本文通过对比两种服务的特点和实际案例的介绍,帮助读者更好地理解服务状态对系统架构和弹性的影响,为设计更好或更有弹性的系统架构提供了有益的参考。 Word count: 200 words.
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《左耳听风》,新⼈⾸单¥98
《左耳听风》,新⼈⾸单¥98
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(26)
- 最新
- 精选
- 流迷的咸菜虽然有状态的服务可以通过sticky session的方式将数据本地化,但是当这个sticky session expire的时候,或者服务处理完成之后,其相关的数据仍然是要同步到数据库中的吧?
作者回复: 不用,一般来说就是一个客户端cookie,或是uid分布一下,或是服务端的一个缓存。
2018-04-122 - 昵称sixcky session和DHT哪里有详细的介绍,这篇文章里好多名词都不认识
作者回复: 自行Google吧
2018-04-031 - 夜行观星皓哥,这篇是在讲是在讲Service Mesh的思想吗?
作者回复: 不是,SM后面的文章会讲
2018-03-061 - mingshun这是近几年所在的团队维护的其中一个重要系统的过程:最初为提高处理性能和水平扩展性,就从有状态往无状态发展。但随着数据量越来越大时,分布式存储就成了瓶颈,经常因为存储系统同步不及时导致不同节点读到的数据不一致。而后又回到有状态,但不在节点间使用分布式存储,因为数据量实在太大。为了在出现故障能快速恢复,每个节点做成双机热备。每改一次架构都要分好几次在周末深夜做数据迁移,多么痛的领悟啊! 理想情况下,计算密集型系统应该让存储向计算方移动,即做成无状态的;存储密集型系统应该让计算向存储移动,即做成有状态的。而上述架构来回修改的最终体会是,当计算和存储都密集的时候,应该整台机器地加,而且每台机器都要求有高的计算和存储性能。 然而说到底,存储其实又是由独立于CPU之外的一个计算单元来处理,本质似乎又回到了计算。现在设计分布式系统时总是先想着怎么分离计算和存储,最终发现计算和存储又是如此密不可分。 感觉我后半段的表述不太成立,打码久了不写人话的后果啊,望谅解!2018-05-22370
- null单体应用跟微服务应用的区别是单体应用是有状态的,微服务应用的是无状态的;单体应用向微服务应用的发展的一个重要体现就是将应用的状态从应用实例中转移到第三方中间件中.例如会话信息,传统的Java项目是将会话存储在tomcat等servlet容器中对其他的java应用隔离,这样导致的结果是如果想扩展服务的之后只能扩展单台服务器.而微服务能则将会话技术放到redis等nosql中间件中或者直接存到客户端中(jwt),微服务中的所有实例都可读取到 我认为分布式微服务应用还是无状态的比较好,因为现有的有状态分布式应用技术不成熟,gossip协议会导致羊群响应,导致而且如果数据大的情况下宽带会十分巨大.而现有的微服务解决方案依赖第三方中间件,这些中间件天生支持扩展分布式,让专业的工具做专业的事.如果服务要做到有状态的话每个服务中存储的状态数据需要做到一致(不管请求到达那个实例产生的结果一致),这也需要多分数据冗余,这样的话还不如放在第三方中间件中,像redis,mysql集群分布式方案十分丰富而且用的人也多 其实我们可以在有状态跟无状态之间做折中;我们可以参照java线程内存模型的形式,把第三方中间件当作JVM的主内存,微服务实例当作java线程对于主内存的拷贝,每个java线程只会拷贝自己需要访问的数据,微服务实例可以将数据缓存到guava cache或者ecache等进程级的缓存中;当微服务实例需要访问某个值的时候先去进程级缓存中查找,找不到再到集中式缓存中查找;更新某个值的时候,微服务本身先更新值,再将值更新到集中式缓存中,最好时候mq中间件通知其他的微服务实例更新自己进程中的缓存值,当然这里可以在计算更新值的时候避免缓存击穿事件分布式分布式锁技术2020-01-12314
- Sdylan存在错别字:结点-节点;元数据索引中对应关键-对应关系。本节笔记如下: ## 服务状态 ### 什么是状态 状态:保留程序的一些数据或是上下文: * 程序调用的结果。 * 服务组合下的上下文。 * 服务的配置。 ### 服务状态类型 1. 无状态的服务 * 可以随意扩展或删除节点 * 依赖第三方储存系统以及自身构建缓存,第三方存储系统: * Redis * MySQL * 高可用强一直:ZK/Etcd * 依赖有状态存储服务,存在网络开销;自身构建缓存浪费资源 2. 有状态的服务 * 数据本地化(Data Locality),延时低 * 更高的可用性和更强的一致性 * 特点:请求映射到同一个节点, 出现:Sticky Session 或是 Sticky Connection * 如何实现Sticky Connection * 长链接或一致性hash,出现服务热点问题 * 做到负载和数据均匀方案 * 路由节点 * 元数据索引:映射后端服务实例和请求的对应关系表 * 路由结点:根据元数据索引来路由,而这个元数据索引表会根据后端服务的压力来重新组织相关的映射 * 直连,不好动态扩展 * Gossip 协议,广播节点信息同步元数据 * 案例:Facebook 的 Scuba、 Orleans * 资料:《Making the Case for Building Scalable Stateful Services in the Modern Era》 3. 有无状态服务的对比 无状态的服务需要我们把数据同步到不同的结点上,而有状态的服务通过 Sticky Session 做数据分片(当然,同步有同步的问题,分片也有分片的问题,这两者没有谁比谁好,都有 trade-off)。2019-12-2736
- 北极点这里的这些方案,总体下来感觉架构上需要超丰富的经验!协调一大帮人来弄这个。现在接触到的系统没有这么复杂!有问题一般一个小点一个小点的优化。读了文章还是感觉很收益!谢谢!2018-03-096
- Geek_Heiko阅读笔记小结: 首先,我们先认识到,一个服务的状态通常是包含: 服务处理所需的元数据、与其它服务组合完成一个业务逻辑的组合上下文和服务的配置。 分布式系统架构中,为了便于系统服务增删和调度,往往要求其服务设计成“无状态”的服务,及类似于函数式编程,其中的服务只管描述其处理逻辑和算法,无需在其中保存上述的"状态"。具体到分布式系统的实现方案是,将这些状态,统一耦合到一个高可用的强一致性的第三方状态存储服务中,这过程主要带来了大量的网络开销、业务处理过程的数据同步及其带来的处理速度降低的问题,且每个服务都需要相对额外地耦合且依赖于该第三方服务接口,对应地,已有的优化方案是底层采用分布式文件系统提高状态的调度和同步速度,无状态的服务添加一些缓存机制。 然而,对于一些数据密集型的应用,无状态服务的无法比拟有状态服务的性能和满足实际需求指标。有状态服务的数据存放在本地,处理延迟低,且其可用性和一致性更强。当从另一方面来说,从整个系统的角度来看,服务间的通信和整个系统的各方面如数据和负载的均衡会带来一定的压力。因为业务层面的数据同步需要该服务将保持长连接,随着一个接一个业务的完成需要接入,该服务将很快成为"热点",若没有适时的断开,其资源必将消耗殆尽。现今的处理方式主要是引入一个元数据索引和路由节点,将后端服务和服务请求进行映射,以在一定程度上调和后端服务的压力。还有一种处理方式是不引入其他的,让有状态的服务直接充当路由的功能,每次服务节点的启动将配置的元数据读到内存中,然后系统的各个节点统一采用 Gossip 协议以便达到集群内的相关同步。 最后,一个业务及其所在的系统是有其生命周期及其不断地演化着的,其中的服务可以是无状态的,业务及其所在的系统是不能的(不然就失去其存在的意义)。对于这些"状态”的冗余备份和快速调度,我们采用在运行时只要有机会就进行相关的复制,“状态”的同步,我们采用在前面的操作前后分两阶段提交的方案以保持其一致性。最后一点是,使用合适的分布式文件系统是有状态的服务调度的关键。2020-01-085
- 罗杰.菲の樂突然发现Twitter 的美女工程师 Caitie McCaffrey现在加入微软的Azure了2020-07-143
- slark服务的状态,很简单:有状态、无状态 实际,状态一定都是有的,但服务的状态可以通过服务间的转移,把他们迁移到第三方存储上去。比如Redis、MySQL、Zookeeper/Etcd或者分布式文件系统,通过这样实现了服务的扩缩容和维护便利。但也增加了和第三方系统的耦合,以及请求链路和响应时间。 有状态,通常可以把状态保存在实例的本地,可以保证更高的可用性和更强的一致性。为了让请求落到同一个实例,可能需要采用数据分片的方式,比如用长连接、用hash分片。这样会导致不同节点的请求、数据存储不平衡。所以也通常需要添加路由节点,或者每个实例自己具有路由的功能(相互间需要同步元数据)。同时,在节点奔溃时候,要考虑到如何尽快恢复原始数据,如果有底层分布式文件系统的支持,就会比较便利2020-01-293
收起评论