【算法】分布式共识Paxos

一、引言

        在分布式系统中,一致性是至关重要的一个问题。Paxos算法是由莱斯利·兰伯特(Leslie Lamport)在1990年提出的一种解决分布式系统中一致性问题的算法。

二、算法原理

        Paxos算法的目标是让一个分布式系统中的多个节点就某个值达成一致。算法通过多个阶段的消息传递来确保一致性:

        准备阶段(Prepare):提议者(Proposer)选择一个提案编号n,并向接受者(Acceptor)发送准备请求。

        承诺阶段(Promise):接受者收到准备请求后,如果提案编号n大于它之前承诺过的任何提案编号,则承诺不再接受编号小于n的提案,并将其之前接受的最高编号的提案作为响应发送给提议者。

        接受阶段(Accept):提议者收到足够多的承诺后,发送接受请求给接受者,请求它们接受提案[n, v],其中v是提议者选择的值。

        学习阶段(Learn):一旦接受者接受了某个提案,它会通知学习者(Learner)该提案已被接受。

三、数据结构

Paxos算法主要涉及以下数据结构:

        提案(Proposal):由提案编号和提议的值组成。

        承诺(Promise):包含接受者承诺不再接受编号小于n的提案,以及它之前接受的最高编号的提案。

四、使用场景

Paxos算法适用于以下场景:

        分布式数据库中的日志复制。

        分布式系统中的状态机复制。

        分布式锁服务。

五、算法实现

以下是Paxos算法的伪代码实现:

class Proposer:def propose(value):n = generate提案编号()send_prepare(n) to all Acceptorswait for majority promisesv = determine_value_to_propose(promises)send_accept(n, v) to all Acceptorswait for majority acceptsnotify Learners of accepted proposalclass Acceptor:def on_prepare(request):if request.n > promised_number:promised_number = request.nsend promise with accepted_proposal to Proposerdef on_accept(request):if request.n >= promised_number:promised_number = request.naccepted_proposal = requestsend accepted_proposal to Learnersclass Learner:def on_learn(accepted_proposal):if enough proposals are accepted:chosen_value = accepted_proposal.valueapply chosen_value to state machine

六、其他同类算法对比

  • Raft算法:相比Paxos更易于理解和实现,提供了更明确的领导选举机制。
  • Zab算法:Zookeeper中使用的算法,结合了Paxos的一些元素,并针对特定场景进行了优化。

七、多语言实现

以下是Paxos算法的简化版实现:

Java

import java.util.HashMap;
import java.util.Map;class Acceptor {private int promisedProposalNumber = -1;private int acceptedProposalNumber = -1;private String acceptedValue = null;public synchronized boolean prepare(int proposalNumber) {if (proposalNumber > promisedProposalNumber) {promisedProposalNumber = proposalNumber;return true;}return false;}public synchronized boolean accept(int proposalNumber, String value) {if (proposalNumber >= promisedProposalNumber) {acceptedProposalNumber = proposalNumber;acceptedValue = value;return true;}return false;}public synchronized int getAcceptedProposalNumber() {return acceptedProposalNumber;}public synchronized String getAcceptedValue() {return acceptedValue;}
}class Proposer {private final Map<Integer, Acceptor> acceptors;private int proposalNumber = 0;private String value;public Proposer(Map<Integer, Acceptor> acceptors, String value) {this.acceptors = acceptors;this.value = value;}public void propose() {proposalNumber++;int successfulPrepares = 0;for (Acceptor acceptor : acceptors.values()) {if (acceptor.prepare(proposalNumber)) {successfulPrepares++;}}if (successfulPrepares > acceptors.size() / 2) {int successfulAccepts = 0;for (Acceptor acceptor : acceptors.values()) {if (acceptor.accept(proposalNumber, value)) {successfulAccepts++;}}if (successfulAccepts > acceptors.size() / 2) {System.out.println("Proposal accepted: " + value);} else {System.out.println("Proposal rejected");}} else {System.out.println("Prepare rejected");}}
}public class PaxosExample {public static void main(String[] args) {Map<Integer, Acceptor> acceptors = new HashMap<>();for (int i = 0; i < 5; i++) {acceptors.put(i, new Acceptor());}Proposer proposer1 = new Proposer(acceptors, "Value 1");proposer1.propose();}
}

Python

class Acceptor:def __init__(self):self.promised_proposal_number = -1self.accepted_proposal_number = -1self.accepted_value = Nonedef prepare(self, proposal_number):if proposal_number > self.promised_proposal_number:self.promised_proposal_number = proposal_numberreturn Truereturn Falsedef accept(self, proposal_number, value):if proposal_number >= self.promised_proposal_number:self.accepted_proposal_number = proposal_numberself.accepted_value = valuereturn Truereturn Falsedef get_accepted_proposal(self):return self.accepted_proposal_number, self.accepted_valueclass Proposer:def __init__(self, acceptors, value):self.acceptors = acceptorsself.proposal_number = 0self.value = valuedef propose(self):self.proposal_number += 1successful_prepares = 0for acceptor in self.acceptors:if acceptor.prepare(self.proposal_number):successful_prepares += 1if successful_prepares > len(self.acceptors) // 2:successful_accepts = 0for acceptor in self.acceptors:if acceptor.accept(self.proposal_number, self.value):successful_accepts += 1if successful_accepts > len(self.acceptors) // 2:print(f"Proposal accepted: {self.value}")else:print("Proposal rejected")else:print("Prepare rejected")if __name__ == "__main__":acceptors = [Acceptor() for _ in range(5)]proposer = Proposer(acceptors, "Value 1")proposer.propose()

C++

#include <iostream>
#include <vector>
#include <memory>class Acceptor {
public:Acceptor() : promisedProposalNumber(-1), acceptedProposalNumber(-1) {}bool prepare(int proposalNumber) {if (proposalNumber > promisedProposalNumber) {promisedProposalNumber = proposalNumber;return true;}return false;}bool accept(int proposalNumber, const std::string &value) {if (proposalNumber >= promisedProposalNumber) {acceptedProposalNumber = proposalNumber;acceptedValue = value;return true;}return false;}std::pair<int, std::string> getAcceptedProposal() {return {acceptedProposalNumber, acceptedValue};}private:int promisedProposalNumber;int acceptedProposalNumber;std::string acceptedValue;
};class Proposer {
public:Proposer(std::vector<std::shared_ptr<Acceptor>> &acceptors, const std::string &value): acceptors(acceptors), proposalNumber(0), value(value) {}void propose() {proposalNumber++;int successfulPrepares = 0;for (auto &acceptor : acceptors) {if (acceptor->prepare(proposalNumber)) {successfulPrepares++;}}if (successfulPrepares > acceptors.size() / 2) {int successfulAccepts = 0;for (auto &acceptor : acceptors) {if (acceptor->accept(proposalNumber, value)) {successfulAccepts++;}}if (successfulAccepts > acceptors.size() / 2) {std::cout << "Proposal accepted: " << value << std::endl;} else {std::cout << "Proposal rejected" << std::endl;}} else {std::cout << "Prepare rejected" << std::endl;}}private:std::vector<std::shared_ptr<Acceptor>> &acceptors;int proposalNumber;std::string value;
};int main() {std::vector<std::shared_ptr<Acceptor>> acceptors;for (int i = 0; i < 5; ++i) {acceptors.push_back(std::make_shared<Acceptor>());}Proposer proposer(acceptors, "Value 1");proposer.propose();return 0;
}

Go

package mainimport ("fmt"
)type Acceptor struct {promisedProposalNumber intacceptedProposalNumber intacceptedValue          string
}func NewAcceptor() *Acceptor {return &Acceptor{promisedProposalNumber: -1,acceptedProposalNumber: -1,}
}func (a *Acceptor) Prepare(proposalNumber int) bool {if proposalNumber > a.promisedProposalNumber {a.promisedProposalNumber = proposalNumberreturn true}return false
}func (a *Acceptor) Accept(proposalNumber int, value string) bool {if proposalNumber >= a.promisedProposalNumber {a.acceptedProposalNumber = proposalNumbera.acceptedValue = valuereturn true}return false
}type Proposer struct {acceptors      []*AcceptorproposalNumber intvalue          string
}func NewProposer(acceptors []*Acceptor, value string) *Proposer {return &Proposer{acceptors: acceptors,value:     value,}
}func (p *Proposer) Propose() {p.proposalNumber++successfulPrepares := 0for _, acceptor := range p.acceptors {if acceptor.Prepare(p.proposalNumber) {successfulPrepares++}}if successfulPrepares > len(p.acceptors)/2 {successfulAccepts := 0for _, acceptor := range p.acceptors {if acceptor.Accept(p.proposalNumber, p.value) {successfulAccepts++}}if successfulAccepts > len(p.acceptors)/2 {fmt.Println("Proposal accepted:", p.value)} else {fmt.Println("Proposal rejected")}} else {fmt.Println("Prepare rejected")}
}func main() {acceptors := make([]*Acceptor, 5)for i := range acceptors {acceptors[i] = NewAcceptor()}proposer := NewProposer(acceptors, "Value 1")proposer.Propose()
}

八、实际服务应用场景代码框架

        以下是一个使用Paxos算法实现分布式锁服务的代码框架:

// Java - Distributed Lock Service with Paxos
public class DistributedLockService {private final Proposer proposer;private final Acceptor acceptor;private final Learner learner;public DistributedLockService() {this.proposer = new Proposer();this.acceptor = new Acceptor();this.learner = new Learner();}public boolean lock(String resource) {// Use Paxos to agree on the lock ownerreturn proposer.propose(resource);}public boolean unlock(String resource) {// Use Paxos to agree on releasing the lockreturn proposer.propose(null);}
}

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

2000-2023年上市公司全要素生产率数据LP法(含原始数据+计算代码+结果)

2000-2023年上市公司全要素生产率数据LP法&#xff08;含原始数据计算代码结果&#xff09; 1、时间&#xff1a;2000-2023年 2、指标&#xff1a;stkcd、year、证券代码、固定资产净额、资产总计、负债合计、支付给职工以及为职工支付的现金、购建固定资产无形资产和其他长期…

Monaco 使用 LinkedEditingRangeProvider

Monaco LinkEdit 功能是指同时修改同样的字符串&#xff0c;例如在编辑 Html 时&#xff0c;修改开始标签时会同时修改闭合标签。Monaco 支持自定义需要一起更新的字符串列表。最终效果如下&#xff1a; 首先&#xff0c;通过 registerLinkedEditingRangeProvider 注册 LinkEd…

关键词查找【Knuth-Morris-Pratt (KMP) 算法】

一个视频让你彻底学懂KMP算法_哔哩哔哩_bilibili KMP算法的核心是利用匹配失败后的信息&#xff0c;尽量减少模式串与主串的匹配次数以达到快速匹配的目的。 第一步&#xff1a;计算模式串(子串)和next[j]数组 模式串 前2位字母的next[j]固定是0 和 1 后续字母的nex[j]&…

生成式AI的发展方向是chat还是Agent探讨

生成式 AI 的发展方向&#xff0c;是 Chat 还是 Agent&#xff1f; 随着生成式AI技术的不断进步&#xff0c;关于其未来发展方向的讨论也愈发激烈。究竟生成式AI的未来是在对话系统&#xff08;Chat&#xff09;中展现智慧&#xff0c;还是在自主代理&#xff08;Agent&#x…

MySQL之触发器和存储过程

1、触发器 触发器简介 触发器&#xff08;trigger&#xff09;是一个特殊的存储过程&#xff0c;它的执行不是由程序调用&#xff0c;也不是手工启动&#xff0c;而是由事件来触 发&#xff0c;比如当对一个表进行操作&#xff08; insert&#xff0c;delete&#xff0c; upda…

js返回一个月的所有天数,用数组表示

直接上代码 import dayjs from dayjs import isSameOrBefore from dayjs/plugin/isSameOrBefore dayjs.extend(isSameOrBefore)function getCurrentMonthDays(month) {const firstDay dayjs().startOf(month);const lastDay dayjs().endOf(month);const allDatesInMonth []…

【C++笔试强训】day05

游游的you 思路 贪心&#xff1a;优先组成 you&#xff0c;最少的字母决定了you的数量。需要注意&#xff1a;如果oo剩下n个&#xff0c;那么相邻oo的个数是n-1个&#xff0c;而不是n/2个。 例如 oooooo oo oo oooo oo 6个o&#xff0c;两两组合有3对&#xff0c;掐头去尾有…

【支持语言模型和视觉语言模型的推理引擎sglang】

介绍 sglang是一个AI推理引擎&#xff0c;是一个专门为大语言模型和视觉语言模型设计的高效服务框架。 就像F1赛车需要顶级发动机一样&#xff0c;大语言模型也需要高效的推理引擎来发挥潜力。 而sglang正是这样一个性能怪兽。 根据LMSys组织的官方公告&#xff0c;最新的s…

CCS(Code Composer Studio 10.4.0)编译软件中文乱码怎么解决

如果是所有文件都出现了中文乱码这时建议直接在窗口首选项中修改&#xff1a;选择"Window" -> "Preferences"&#xff0c;找到"General" -> "Workspace"&#xff0c;将"Text file encoding"选项设置为"Other&quo…

Mac printf处理参数的奇特之处(macOS中,printf使用%d输出一个浮点数会发生什么情况?)

今天早上网上冲浪的时候看到了 2016 年的一篇文章&#xff0c;里面提到了一段代码&#xff1a; #include <stdio.h> int main() {double a 10;printf("a %d\n", a);return 0; }说这段代码在 x86&#xff08;IA-32&#xff09;上运行时&#xff0c;输出为0&a…

Java语言程序设计——篇八(1)

&#x1f33f;&#x1f33f;&#x1f33f;跟随博主脚步&#xff0c;从这里开始→博主主页&#x1f33f;&#x1f33f;&#x1f33f; Java常用核心类 主要内容Object: 终极父类toString( )方法equals( )方法getClass( )方法hashCode( )方法clone( )方法finalize( )方法实战演练 …

c语言之给三个数字排大小

写代码将三个整数数按从大到小输出。 例如&#xff1a; 输入&#xff1a;2 3 1 输出&#xff1a;3 2 1 首先三个整数从大到小排&#xff0c;先创建三个变量 输入数字大小 通过冒泡排序派大小最后在输出出来。 简单介绍一下冒泡排序&#xff0c;后期在完整的写出来 冒泡排…

文件上传总结

一、原理 通过界面上的上传功能上传了一个可执行的脚本文件&#xff0c;而WEB端的系统并未对其进行检测或者检测的逻辑做的不够好&#xff0c;使得恶意用户可以通过文件中上传的一句话木马获得操控权 二、绕过方法 1>前端绕过 1.删除前端校验函数 checkFile() 2.禁用js…

华为Ascend C算子开发(中级)考试

华为Ascend C算子开发&#xff08;中级&#xff09;考试题 提示&#xff1a;这个是河北廊坊Ascend C算子开发考试题和答案&#xff0c;仅供参考&#xff0c;因为不确定其他城市的考试题是否也是一样 文章目录 华为Ascend C算子开发&#xff08;中级&#xff09;考试题一、op_ho…

捉虫笔记(1)之 WinDbg符号配置

WinDbg符号配置 1、WinDbg简单介绍 WinDbg 是微软的一款强大的调试工具&#xff0c;用于 Windows 平台的内核和用户模式调试。它提供了一系列强大的功能&#xff0c;包括内存和寄存器的查看、断点设置、堆栈跟踪、性能分析等。 WinDbg 的历史可以追溯到微软早期的调试工具&a…

最新风车IM即时聊天源码及完整视频教程2024年7月版

堡塔面板 试验性Centos/Ubuntu/Debian安装命令 独立运行环境&#xff08;py3.7&#xff09; 可能存在少量兼容性问题 不断优化中 curl -sSO http://io.bt.sy/install/install_panel.sh && bash install_panel.sh 1.宝塔环境如下: Nginx 1.20 Tomcat 8 MySQL 8.0 R…

从0到1搭建一个组件库

最近我开启了一个新项目&#xff0c;基于echarts进行二次封装&#xff0c;希望能为Vue3项目量身打造一套高效、易用的图表组件库&#xff0c;取名为 v-echarts。 目前雏形已经搭建完成&#xff0c;先把整个搭建过程做一个记录。后续再持续迭代、完善该图表组件库。 v-echarts 文…

RustDesk远程控屏软件使用教学

RustDesk自建服务器使用教学RustDesk远程控屏软件使用教学 下载软件后 右键管理员运行 点击右上角设置按钮 管理员运行 保证启动服务 点击左侧导航栏网络按钮 复制域名或者ip地址到 ID服务器 输入框 然后点击应用即可

移动式气象站:科技赋能,精准预报的新篇章

在这个气候多变、极端天气频发的时代&#xff0c;气象信息的准确性与及时性成为了社会各界关注的焦点。从农业生产到城市规划&#xff0c;从航空航海到日常生活&#xff0c;气象服务无处不在&#xff0c;其重要性不言而喻。而在这场气象科技的变革中&#xff0c;移动式气象站以…

友思特应用 | 硅片上的光影贴合:UV-LED曝光系统在晶圆边缘曝光中的高效应用

导读 晶圆边缘曝光是帮助减少晶圆涂布过程中多余的光刻胶对电子器件影响的重要步骤。友思特 ALE/1 和 ALE/3 UV-LED 高性能点光源&#xff0c;作为唯一可用于宽带晶圆边缘曝光的 i、h 和 g 线的 LED 解决方案&#xff0c;可高效实现WEE系统设计和曝光需求。 晶圆边缘曝光及处…