分布式系统服务单点问题的探讨

article/2025/10/4 19:25:07

分布式系统服务单点问题的探讨

    • 无状态服务的单点问题
    • 有状态服务的单点问题

在分布式系统中,单点问题是一个比较常见的问题,对于单点问题可以分为有状态服务的单点问题和无状态服务的单点问题。

无状态服务的单点问题

对于无状态的服务,单点问题的解决比较简单,因为服务是无状态的,所以服务节点很容易进行平行扩展。比如,在分布式系统中,为了降低各进程通信的网络结构的复杂度,我们会增加一个代理节点,专门做消息的转发,其他的业务进行直接和代理节点进行通信,类似一个星型的网络结构。
无状态单点
无状态多节点
参考上面两个图,图中proxy是一个消息转发代理,业务进程中的消息都会经过该代理,这也是比较场景的一个架构。在上图中,只有一个proxy,如果该节点挂了,那么所有的业务进程之间都无法进行通信。由于proxy是无状态的服务,所以很容易想到第二个图中的解决方案,增加一个proxy节点,两个proxy节点是对等的。增加新节点后,业务进程需要与两个Proxy之间增加一个心跳的机制,业务进程在发送消息的时候根据proxy的状态,选择一个可用的proxy进行消息的传递。从负载均衡的角度来看,如果两个proxy都是存活状态的话,业务进程应当随机选择一个proxy。
那么该解决方案中会存在什么问题呢?
主要存在的问题是消息的顺序性问题。一般来说,业务的消息都是发送、应答,再发送、再应答这样的顺序进行的,在业务中可以保证消息的顺序性。但是,在实际的应用中,会出现这样一个情况:在业务进程1中,有个业务需要给业务进程3发送消息A和消息B,根据业务的特性,消息A必须要在消息B之前到达。如果业务进程1在发送消息A的时候选择了proxy1,在发送消息B的时候选择了proxy2,那么在分布式环境中,我们并不能确保先发送的消息A一定就能比后发送的消息B先到达业务进程3。那么怎么解决这个问题?其实方案也比较简单,对于这类对消息顺序有要求的业务,我们可以指定对应的proxy进行发送,比如消息A和消息B都是使用proxy1进行发送,这样就可以保证消息A比消息B先到达业务进程3。
整体来说,对于无状态的服务的单点问题的解决方案还是比较简单的,只要增加对应的服务节点即可。

有状态服务的单点问题

相对无状态服务的单点问题,有状态服务的单点问题就复杂多了。如果在架构中,有个节点是单点的,并且该节点是有状态的服务,那么首先要考虑的是该节点是否可以去状态,如果可以,则优先选择去除状态的方案(比如说把状态存储到后端的可靠DB中,可能存在性能的损耗),然后就退化成了一个无状态服务的单点问题了,这就可以参考上一节的方案了。
但是,并不是所有的服务都是可以去状态的,比如说对于一些业务它只能在一个节点中进行处理,如果在不同的节点中处理的话可能会造成状态的不一致,这类型的业务是无法去除状态的。对于这种无法去除状态的单点的问题的解决方案也是有多种,但是越完善的方案实现起来就越复杂,不过整体的思路都是采用主备的方式。
简单主备
第一个方案就是就是增加一个备用节点,备用节点和业务进程也可以进行通信,但是所有的业务消息都发往Master节点进行处理。Master节点和Slave节点之间采用ping的方式进行通信。Slave节点会定时发送ping包给Master节点,Master节点收到后会响应一个Ack包。当Slave节点发现Master节点没有响应的时候,就会认为Master节点挂了,然后把自己升级为Master节点,并且通知业务进程把消息转发给自己。该方案看起来也是挺完美的,好像不存在什么问题,Slave升级为Master后所有的业务消息都会发给它。但是,如果在Master内部有一些自己的业务逻辑,比如说随机生成一些业务数据,并且定时存档。那么当Master和Slave之间的网络出现问题的时候,Slave会认为Master挂了,就会升级为Master,同样会执行Master的相应的业务逻辑,同样也会生成一些业务数据回写到DB。但是,其实Master是没有挂的,它同样也在运行对应的业务逻辑(即使业务进程的消息没有发给旧的Master了),这样就会出现两个Master进行写同一份数据了,造成数据的混乱。所以说,该方案并不是一个很好的方案。
那么怎么解决可能会出现多个Master的问题?
换个角度看,该问题其实就是怎么去裁决,哪个节点是Master的问题。
方案一:引入第三方的服务进行裁决。
我们可以引入ZooKeeper,由ZooKeeper进行裁决。同样,我们启动两个主节点,“节点A”和节点B。它们启动之后向ZooKeeper去注册一个节点,假设节点A注册的节点为master001,节点B注册的节点为master002,注册完成后进行选举,编号小的节点为真正的主节点。那么,通过这种方式就完成了对两个Master进程的调度。
ZooKeeper托管主节点

ZooKeeper
ZooKeeper有一套机制,可以保证不会出现多个Master的情况,具体可以参考:
https://segmentfault.com/a/1190000012185322
方案二: 通过选举算法和租约的方式实现Master的选举
对于方案一的缺点主要要多维护一套ZooKeeper的服务,如果原本业务上并没有部署该服务的话,要增加该服务的维护也是比较麻烦的事情。这个时候我们可以在业务进程中加入Master的选举方案。目前有比较成熟的选举算法,比如Paxos和Raft。然后再配合租约机制,就可以实现Master的选举,并且确保当前只有一个Master的方案。但是,这些选举算法理解起来并不是那么地容易,要实现一套完善的方案也是挺难的。所以不建议重复造轮子,业内有很多成熟的框架或者组件可以使用,比如微信的PhxPaxos。
Paxos选举
比如上图的方案中,三个节点其实都是对等的,通过选举算法确定一个Master。为了确保任何时候都只能存在一个Matster,需要加入租约的机制。一个节点成为Master后,Master和非Master节点都会进行计时,在超过租约时间后,三个节点后可以发起“我要成为Master”的请求,进行重新选举。由于三个节点都是对等的,任意一个都可以成为Master,也就是说租期过后,有可能会出现Master切换的情况,所以为了避免Master的频繁切换,Master节点需要比另外两个节点先发起自己要成为Master的请求(续租),告诉其他两个节点我要继续成为Master,然后另外两个节点收到请求后会进行应答,正常情况下另外两个节点会同意该请求。关键点就是,在租约过期之前,非Master节点不能发起“我要成为Master”的请求,这样就可以解决Master频繁切换的问题。


http://chatgpt.dhexx.cn/article/Cv5s2mCB.shtml

相关文章

08-微服务版单点登陆系统(SSO)实践

文章目录 单点登陆系统简介背景分析单点登陆系统概述单点登陆系统解决方案设计 单点登陆系统初步设计服务设计工程结构设计 SSO父工程创建及初始化创建父工程父工程pom文件初始配置 系统基础服务工程设计及实现业务描述表结构设计工程数据初始化创建系统服务工程并初始化Pojo对…

IDEA同时打开多个项目之解决方法

对于我们开发人员来说,有时想在一个窗口中打开多个项目,这时打开新项目时只有两个选项: 覆盖本窗口项目/在新窗口打开 解决方法: 1、点击左上角 File--->Project Structure: 2、然后选择Modules这一栏&#xff0c…

idea一个工作空间打开多个项目

很多时候,多个项目之间并不是parent和module的关系,如果不是parent和module的关系,idea一个工作空间只能打开一个项目,这样的话,如果有多个项目,来回切换视图让人烦不胜烦。下面介绍个在idea一个工作空间打…

Idea打开多个项目文件时,不自动识别maven项目

问题描述 idea打开多个项目文件(直接打开的多个项目的文件夹),却没有识别出maven项目。网上查阅,解决方案为: 选中项目的pom.xml文件,右键-" add as maven project"。 但由于项目过多,不方便一个…

idea在一个窗口打开多个项目

1、.将两个项目或多个项目放在同一个文件夹下(等同于eclipse中将多个项目放在工作空间workspace下),lz在D盘下创建了ideaCloudProject文件夹,并在该文件夹下创建了一个cloud项目和一个vue项目,如下图: 2、用idea打开该…

一个IDEA界面如何同时打开多个项目

第一步:先导入其中一个工程 第二步:点击File->Project Structure 第三步:导入模块 最后点击Apply即可完成一个IDEA界面同时打开多个项目的需求。

怎么在IDEA的一个窗口中打开多个项目

之前一直使用的是sts,最近比较有空,学习一下idea的使用。 习惯了eclipse,myeclipse,sts等工具,想在一个窗口管理多个项目,只用import就可以了。但今天使用Intellij IDEA时,新建了一个工程,然后我又想从github上把我以前…

IDEA中如何在一个窗口中打开多个项目

idea在一个窗口如何打开多个项目 在使用Spring进行微服务开发时,需要同时打开很多个项目,但是如果每一个项目都单独一个窗口的话,切换就很麻烦,最方便的就是在IDEA一个窗口中管理多个项目。 在IDEA之中,它的一个项目就…

idea同时打开多个项目

想在idea中同时打开多个项目,如下图 打开项目后一般无法识别多个文件,可以按照下面的步骤操作 查看项目中maven插件是否打开 查看maven是否配置 查看右侧是否有maven选项,如果没有就先添加maven选项,添加方案步骤提供下面三种方…

使用IDEA打开eclipse项目

文章目录 点击左上角的File→New→Project from Existing Sources。 选择到要打开的项目路劲,选择好后点击OK 先勾选 Import project from external model 后选择Eclipse后点击Next。 无需设置,直接点击Next。 继续点击Next。 继续Next。 选择运行项目的…

idea关闭多个项目合并在tab栏显示

macos bigsur使用新版idea 2021.2 打开多个项目合并到tab栏: 对于屏幕比较小多了一行感觉比较别扭,以及全屏下暂时没适应……好几次都感觉找不到桌面…… 关闭:这个关闭是mac级别的关闭,并不是idea的setting macos - 系统偏好 …

IDEA设置多窗口打开项目

问题: 解决IDEA打开项目总是在当前窗口下,无法同事打开两个窗口的问题。【可能是我自己默认配置的问题】 解决: 菜单栏File,进入Setting栏 如上图所示,配置即可~~ 转载于:https://www.cnblogs.com/hyc-ana/p/9187153.h…

【Mac】在Idea中打开两个项目在同一个窗口

前置条件: 打开两个项目在不同窗口 步骤: 1.选择一个窗口上的window(窗口)选项。 2.选择Merge All Project Windows(合并所有项目窗口) 效果: 注意事项: 一定要打开多个项目&am…

MAC设置idea多个项目合并在tab栏显示

这个是mac级别的设置,并不是idea的设置。系统偏好 - 通用 - 始终 : 另外IDEA打开新项目时应选择new window

idea在一个窗口打开一个文件夹里的多个项目

使用场景:Spring-cloud框架下的项目一般都有多个子项目,就像我们项目由6个子项目,每个子项目单独更新很麻烦,还有相互之间的依赖,所以就把所有的子项目都放到一个文件夹下,只要更新所有的子项目都会更新&am…

Intellij IDEA同时打开多个工程(项目)的方法

这里介绍两中方法: 方法一: 先创建一个文件夹命名为workspace(可以自定义名称) 将开发项目放在该workspace目录下 打开Intellij idea 开发工具,选择 File -> Open 在Open File or Project 窗口中,找到…

Mac 下IDEA 在同一窗口下打开多个项目

Mac 系统的IDEA 升级之后可以支持在同一个窗口下打开多个项目,就像这样: Mac 设置如下:

Idea-如何像eclipse一样一个窗口打开多个项目

1.打开IDEA → 选择 【file】→【new】→[Project] 2.选择【Empty Project】 创建一个空项目 点击【Next】 3.输入项目空间名   4.选择打开的位置 选择【This Window】 当前工作空间就会变成你创建的那个 我的是‘untitled’ 到这个步骤就把我们需要的工作空间建立好啦&am…

idea设置打开多个窗口

idea默认是打开10个窗口,超过10个后,会关掉前面打开的窗口,这在开发的时候会很难受, File->settings->Editor->General->Editor Tabs->closing Policy->Tab limit 设置窗口个数,调大数值&#xff0…

IDEA界面同时打开多个项目

(1)首先打开一个项目 (2)File - Project Structure - Modules - 号 (3) 选择import module ,选择相应项目目录,选择maven,确定即可