微服务-理论(CAP,一致性协议)

CAP理论

关于CAP理论的介绍可以直接看这篇文章

CAP分别是什么?

一致性(Consistency
一致性包括强一致性,弱一致性,最终一致性。
一致性其实是指数据的一致性,为什么数据会不一致呢?
在这里插入图片描述

如上面这张图,我们服务是以集群的方式向外提供服务,客户端并不会关心我这次请求到了那个节点。如果我第一次请求到了A节点做了更新数据的操作,但是第二次我的请求被转发到B节点了。如果这个时候服务A和服务B的数据还没有进行同步,这个时候数据就不一致了,事实上我们也很难做到服务A的数据发生变化就可以立即传给B进行同步,特别是在请求特别频繁的情况下。因此要根据实际场景去判断是否一定要保证强一致性。例如涉及金钱和库存的这种服务集群肯定是要保证强一致性的。又例如点赞量和播放量或者访问量,这些并不需要实时一致,保证最终一致即可。

可用性(Availability)
其实就是不管数据正不正确,只要用户来请求,就返回给用户数据。
在我们说一致性的时候,如果去保证强一致性,这个时候客户端如果请求到达了B是不能对外提供服务的,因为一旦提供服务这个数据还是老的数据,就产生了数据的不一致性。但是如果不提供服务的话,那这个服务节点岂不是不可以用了吗?那就是没有保障可用性呀。所以我们也可以看到,一致性和可用性之间是需要做一定妥协的。

分区容错性(Partition tolerance)

1 分区
什么是分区,分布式系统分布在多个子网络中。分布式系统的服务节点可能由于网络原因,或者其它因素不能相互通信。这种情况就叫产生了分区。
在这里插入图片描述

2 什么是分区容忍?
因为产生分区这种情况一般来说是无法避免的,我们不能完全保证两个服务节点能够完全互通,不产生任何异常。

总结下来就是在一个分布式系统中,这个P分区是一定存在的。我们需要根据业务场景来做C和A的一些取舍。

常见组件保证的模式

  • Nacos 保证了AP + CP
  • Zookeeper 保证了CP
  • Eureka 保证了AP

Distro 一致性协议(临时节点协议)

原文链接
distro协议网上的资料比较少,因为它是阿里“自创的协议“,通过源码总结一下distro协议的关键点:
distro协议是为了注册中心而创造出的协议;
客户端与服务端有两个重要的交互,服务注册与心跳发送;
客户端以服务为维度向服务端注册,注册后每隔一段时间向服务端发送一次心跳,心跳包需要带上注册服务的全部信息,在客户端看来,服务端节点对等,所以请求的节点是随机的;
客户端请求失败则换一个节点重新发送请求;
服务端节点都存储所有数据,但每个节点只负责其中一部分服务,在接收到客户端的“写“(注册、心跳、下线等)请求后,服务端节点判断请求的服务是否为自己负责,如果是,则处理,否则交由负责的节点处理;
每个服务端节点主动发送健康检查到其他节点,响应的节点被该节点视为健康节点;
服务端在接收到客户端的服务心跳后,如果该服务不存在,则将该心跳请求当做注册请求来处理;
服务端如果长时间未收到客户端心跳,则下线该服务;
负责的节点在接收到服务注册、服务心跳等写请求后将数据写入后即返回,后台异步地将数据同步给其他节点;
节点在收到读请求后直接从本机获取后返回,无论数据是否为最新。
新节点同步机制:
DistroProtocol#startDistroTask

private void startDistroTask() {if (EnvUtil.getStandaloneMode()) {isInitialized = true;return;}// 健康检查startVerifyTask();// 开始加载startLoadTask();
}

平等机制:
Nacos 的每个节点是平等的,都可以处理写的请求
异步复制机制:
DistroProtocol#sync

public void sync(DistroKey distroKey, DataOperation action) {sync(distroKey, action, DistroConfig.getInstance().getSyncDelayMillis());}

健康检查机制:
DistroProtocol#startDistroTask

private void startVerifyTask() {GlobalExecutor.schedulePartitionDataTimedSync(new DistroVerifyTimedTask(memberManager, distroComponentHolder,distroTaskEngineHolder.getExecuteWorkersManager()),DistroConfig.getInstance().getVerifyIntervalMillis());
}

本地读机制(每个节点拥有全量的数据):
但是写处理,是只有一部分数据,也就是有个数据拆分,分而治之的机制。
InstanceController#list

/*** Get all instance of input service.** @param request http request* @return list of instance* @throws Exception any error during list*/@GetMapping("/list")@Secured(action = ActionTypes.READ)public Object list(HttpServletRequest request) throws Exception {}

路由转发机制:
DistroFilter#doFilter

if (distroMapper.responsible(distroTag)) {filterChain.doFilter(req, resp);return;}

在这里插入图片描述

Raft 一致性协议(持久化节点协议)

该协议主要是发起选举,选举后如何同步数据。一个节点起来了以后,会发起投票,如果集群过半数据认可这个节点则这个节点为leader,成为leader后与其它节点建立联系。
V1版本的选举与同步

try {if (stopWork) {return;}if (!peers.isReady()) {return;}RaftPeer local = peers.local();local.leaderDueMs -= GlobalExecutor.TICK_PERIOD_MS;if (local.leaderDueMs > 0) {return;}// 来到这里以后已经和Master失联了// reset timeoutlocal.resetLeaderDue();local.resetHeartbeatDue();// 发起投票,里面会向其它节点发起异步请求sendVote();} catch (Exception e) {Loggers.RAFT.warn("[RAFT] error while master election {}", e);}
// 过半
if (maxApproveCount >= majorityCount()) {RaftPeer peer = peers.get(maxApprovePeer);peer.state = RaftPeer.State.LEADER;if (!Objects.equals(leader, peer)) {leader = peer;ApplicationUtils.publishEvent(new LeaderElectFinishedEvent(this, leader, local()));Loggers.RAFT.info("{} has become the LEADER", leader.ip);}
}// 处理心跳
try {if (stopWork) {return;}if (!peers.isReady()) {return;}RaftPeer local = peers.local();local.heartbeatDueMs -= GlobalExecutor.TICK_PERIOD_MS;if (local.heartbeatDueMs > 0) {return;}local.resetHeartbeatDue();sendBeat();} catch (Exception e) {Loggers.RAFT.warn("[RAFT] error while sending beat {}", e);}

V2版本的选举与同步
涉及源码
com.alibaba.nacos.naming.consistency.DelegateConsistencyServiceImpl
com.alibaba.nacos.naming.consistency.persistent.PersistentConsistencyServiceDelegateImpl#PersistentConsistencyServiceDelegateImpl
com.alibaba.nacos.naming.consistency.persistent.impl.PersistentServiceProcessor#afterConstruct
com.alibaba.nacos.core.distributed.raft.JRaftProtocol#addRequestProcessors
com.alibaba.nacos.core.distributed.raft.JRaftServer#createMultiRaftGroup
com.alipay.sofa.jraft.RaftGroupService#start(boolean)
com.alipay.sofa.jraft.RaftServiceFactory#createAndInitRaftNode
com.alipay.sofa.jraft.core.NodeImpl#init
com.alipay.sofa.jraft.core.NodeImpl#electSelf
com.alipay.sofa.jraft.core.NodeImpl#becomeLeader
同步
com.alipay.sofa.jraft.ReplicatorGroup#addReplicator(com.alipay.sofa.jraft.entity.PeerId)
部分源码

private BasePersistentServiceProcessor createNewPersistentServiceProcessor(ProtocolManager protocolManager,ClusterVersionJudgement versionJudgement) throws Exception {final BasePersistentServiceProcessor processor =EnvUtil.getStandaloneMode() ? new StandalonePersistentServiceProcessor(versionJudgement): new PersistentServiceProcessor(protocolManager, versionJudgement);processor.afterConstruct();return processor;}

PersistentServiceProcessor#afterConstruct

@Override
public void afterConstruct() {super.afterConstruct();String raftGroup = Constants.NAMING_PERSISTENT_SERVICE_GROUP;this.protocol.protocolMetaData().subscribe(raftGroup, MetadataKey.LEADER_META_DATA, o -> {if (!(o instanceof ProtocolMetaData.ValueItem)) {return;}Object leader = ((ProtocolMetaData.ValueItem) o).getData();hasLeader = StringUtils.isNotBlank(String.valueOf(leader));Loggers.RAFT.info("Raft group {} has leader {}", raftGroup, leader);});this.protocol.addRequestProcessors(Collections.singletonList(this));// If you choose to use the new RAFT protocol directly, there will be no compatible logical executionif (EnvUtil.getProperty(Constants.NACOS_NAMING_USE_NEW_RAFT_FIRST, Boolean.class, false)) {NotifyCenter.registerSubscriber(notifier);waitLeader();startNotify = true;}
}

JRaft

public void init(RaftConfig config) {if (initialized.compareAndSet(false, true)) {this.raftConfig = config;NotifyCenter.registerToSharePublisher(RaftEvent.class);this.raftServer.init(this.raftConfig);this.raftServer.start();// There is only one consumer to ensure that the internal consumption// is sequential and there is no concurrent competitionNotifyCenter.registerSubscriber(new Subscriber<RaftEvent>() {@Overridepublic void onEvent(RaftEvent event) {Loggers.RAFT.info("This Raft event changes : {}", event);final String groupId = event.getGroupId();Map<String, Map<String, Object>> value = new HashMap<>();Map<String, Object> properties = new HashMap<>();final String leader = event.getLeader();final Long term = event.getTerm();final List<String> raftClusterInfo = event.getRaftClusterInfo();final String errMsg = event.getErrMsg();// Leader information needs to be selectively updated. If it is valid data,// the information in the protocol metadata is updated.MapUtil.putIfValNoEmpty(properties, MetadataKey.LEADER_META_DATA, leader);MapUtil.putIfValNoNull(properties, MetadataKey.TERM_META_DATA, term);MapUtil.putIfValNoEmpty(properties, MetadataKey.RAFT_GROUP_MEMBER, raftClusterInfo);MapUtil.putIfValNoEmpty(properties, MetadataKey.ERR_MSG, errMsg);value.put(groupId, properties);metaData.load(value);// The metadata information is injected into the metadata information of the nodeinjectProtocolMetaData(metaData);}@Overridepublic Class<? extends Event> subscribeType() {return RaftEvent.class;}});}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/590934.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

下界通配符(? super Type)

在Java中&#xff0c;? super Type是一个下界通配符&#xff0c;表示参数化类型的下限是Type。这意味着容器可以持有Type类型的任何对象或者Type的父类型对象。 使用场景 这种类型的通配符通常用于泛型方法中&#xff0c;允许方法接受Type的实例或其父类型的集合。这是基于PE…

【最优化方法】对称矩阵的对角化

文章目录 正交化方法示例 矩阵正交化 正交化方法 设 R n R^n Rn 中线性无关组 a 1 , a 2 , a 3 , … , a n a_1,a_2,a_3,\dots,a_n a1​,a2​,a3​,…,an​&#xff0c;令 β 1 α 1 β 2 α 2 − [ α 2 β 1 ] ∣ ∣ β 1 ∣ ∣ β 1 β 3 α 3 − [ α 3 β 1 ] ∣ ∣…

oCPC实践录 | 目标ROI的出价与转化回传调控算法

这篇文章我们聊聊广告主在oCPC下&#xff0c;怎么调控自己的出价或者回传转化优化自己的ROI。 ROI是广告主最关心的指标了&#xff0c;根据oCPC出价的基本原理ocpc_bid pcvr * given_cpa * k, 广告主在整个出价中有两个可以控制的变量来影响出价&#xff0c;一个是直接的give…

NB-IoT BC260Y Open CPU SDK⑱ctlwm2m连接天翼物联CWing平台

NB-IoT BC260Y Open CPU SDK⑱ctlwm2m连接天翼物联CWing平台 1、平台介绍2、SDK支持CTLWM2M协议2、CTLWM2M API的使用3、软件设计1)、上报业务数据2)、上报报警事件3)、上报故障事件4)、接收平台数据并应答5)、根据唤醒模式触发不同的应用4、实例分析5、以下是调试的结果:…

Redis缓存穿透,缓存击穿,缓存雪崩

文章目录 Redis缓存穿透&#xff0c;缓存击穿&#xff0c;缓存雪崩1. 缓存穿透1.1 解决方案1&#xff1a;缓存空数据1.2 解决方案2&#xff1a;使用布隆过滤器1.2.1 布隆过滤器介绍 2. 缓存击穿2.1 解决方案1&#xff1a;互斥锁2.2 解决方案2&#xff1a;逻辑过期 3. 缓存雪崩3…

NumPy 中级教程——随机数生成

Python NumPy 中级教程&#xff1a;随机数生成 在数据科学、机器学习和统计学等领域中&#xff0c;随机数生成是一个关键的操作。NumPy 提供了丰富的随机数生成功能&#xff0c;包括生成服从不同分布的随机数、设置随机种子等。在本篇博客中&#xff0c;我们将深入介绍 NumPy …

【漏洞复现】OpenSSH ProxyCommand命令注入漏洞(CVE-2023-51385)

文章目录 前言一、漏洞背景二、漏洞详情三、影响范围四、漏洞验证 前言 OpenSSH存在命令注入漏洞&#xff08;CVE-2023-51385&#xff09;&#xff0c;攻击者可利用该漏洞注入恶意Shell字符导致命令注入。 一、漏洞背景 OpenSSH 是 SSH &#xff08;Secure SHell&#xff09…

Oracle笔记-查看表已使用空间最大空间

目前以Oracle18c为例&#xff0c;主要是查这个表USER_SEGMENTS。 在 Oracle 18c 数据库中&#xff0c;USER_SEGMENTS 是一个系统表&#xff0c;用于存储当前用户&#xff08;当前会话&#xff09;拥有的所有段的信息。段是 Oracle 中分配存储空间的逻辑单位&#xff0c;用于存…

HTTP协议编程实战(二)实战二

使用析构函数主要是在里面关闭套接字&#xff08;socket&#xff09;; waitForReadyRead()里面参数是毫秒&#xff0c;失败返回false; \r\n表示请求头部已经结束了&#xff0c;HTTP/1.1是版本号&#xff0c;200 ok表示请求响应成功 关闭的话就在前面加/

javaScript中的常用事件

文章目录 javaScript中什么是事件&#xff1f;基本原理javaScript中的时间使用1&#xff0c;窗口事件1.1、onblur1.2、onfocus1.3、onload1.4、onresize 2&#xff0c;表单事件2.1、onchange2.2、**oninput**2.3、oninvalid2.4、onselect2.5、onsubmit 3&#xff0c;键盘事件3.…

国科大图像处理2023速通期末——汇总2017-2019

国科大2023.12.28图像处理0854期末重点 图像处理 王伟强 作业 课件 资料 一、填空 一个阴极射线管它的输入与输出满足 s r 2 sr^{2} sr2&#xff0c;这将使得显示系统产生比希望的效果更暗的图像&#xff0c;此时伽马校正通常在信号进入显示器前被进行预处理&#xff0c;令p…

记录爬虫编写步骤

本文讲解 Python 爬虫实战案例&#xff1a;抓取百度贴吧&#xff08;https://tieba.baidu.com/&#xff09;页面&#xff0c;比如 Python爬虫吧、编程吧&#xff0c;只抓取贴吧的前 5 个页面即可。今天一个毕业学生问到一个问题&#xff1a;不清楚编写爬虫的步骤&#xff0c;不…

TF-IDF(Term Frequency-Inverse Document Frequency)算法 简介

TF-IDF&#xff08;Term Frequency-Inverse Document Frequency&#xff09;是一种用于信息检索和文本挖掘的常用算法。它用于评估一个词对于一个文档集合中某个文档的重要性。 这个算法的基本思想是&#xff1a;如果一个词在一个文档中频繁出现&#xff0c;并且在整个文档集合…

计算机网络第一课

先了解层级&#xff1a; 传输的信息称为协议数据单元&#xff08;PDU&#xff09;&#xff0c;PDU在每个层次的称呼都不同&#xff0c;见下图&#xff1a;

我的CSDN 512天创作者纪念日总结:高效、高现

文章目录 512天创作者纪念日&#xff1a;2023年的12月31日CSDN的512天消息提醒第一篇文章&#xff0c;最后一篇文章总计847篇文章&#xff0c;每月发文分布512天&#xff0c;各专栏文章统计512天&#xff0c;互动总成绩 512天创作者纪念日&#xff1a;2023年的12月31日 2023年…

我最喜欢的趣味几何书-读书笔记

我最喜欢的趣味几何书-读书笔记 1、利用阴影的长度来测量 公元前6世纪&#xff0c;古希腊哲学家泰勒思为了测量金字塔&#xff0c;想到了这样的方法&#xff1a;选择了一个特殊的时间&#xff0c;在那个时间&#xff0c;他自身的影子长度刚好跟他的身高相等。此时&#xff0c…

LeetCode 2706. 购买两块巧克力【数组,一次遍历】1207

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

【并发设计模式】聊聊Thread-Per-Message与Worker-Thread模式

在并发编程中&#xff0c;核心就是同步、互斥、分工。 同步是多个线程之间按照一定的顺序进行执行&#xff0c;比如A执行完&#xff0c;B在执行。而互斥是多个线程之间对于共享资源的互斥。两个侧重点不一样&#xff0c;同步关注的是执行顺序&#xff0c;互斥关注的是资源的排…

腾讯云轻量应用服务器详细介绍_2024年更新

腾讯云轻量应用服务器开箱即用、运维简单的轻量级云服务器&#xff0c;CPU内存带宽配置高并且价格特别便宜&#xff0c;大带宽&#xff0c;但是限制月流量。轻量2核2G3M带宽62元一年、2核2G4M优惠价118元一年&#xff0c;540元三年、2核4G5M带宽218元一年&#xff0c;756元3年、…

pyqt5用qtdesign设计页面时,去掉页面的空白界面、边框和标题栏

前言 Windows默认的标题栏有时候自己觉得不太美观&#xff0c;就想自己设计一个&#xff0c;然后把默认的去掉&#xff0c;并且把长方形的边框和多余的空表界面去掉&#xff0c;就是下图中圈出来的区域&#xff1a; 去掉之后的效果如图&#xff1a; 这样我们就可以自定义窗…