操作系统_Paxos协议实现数据一致性更新

news/2024/10/19 23:40:01

一、实验环境

系统:Windows10
编译软件:Visual Studio 2022
语言:C

二、内容

假设由5台服务器Ai(i=1,2..5)组成集群,每份数据在5台服务器中各保留一个副本。当客户端C1和C2同时修改存储在集群中的同一个数据时,由于网络修改延迟的存在无法保证两个数据的请求到达每台服务器的先后顺序。其次,可能会出现C1的请求先到达A1服务器,而C2的请求先到达A2服务器的情况。这种情况下,在A1和A2服务器上对数据的修改顺序不同,而修改顺序的不同直接导致了这两个副本数据的不一致。要保证修改保持副本一致只要保证在每台服务器上对数据的操作顺序相同。修改操作的顺序相同的最简单方法是采用PrimarySecondary模式,所有对数据修改的操作都先发送到Primary主机,然后由
Primary主机分发给Secondary主机,此时操作的顺序由Primary主机决定。但这种方法存在单点故障问题。请使用PAXOS协议,设计一个数据更新方案,保证每台服务器数据的一致性。

方案原理如下:
在 Paxos 中,决策的过程分为两个主要阶段:准备阶段和提议阶段。这两个阶段确保了服务器和客户能够达成一致,即使消息丢失或部分人掉线也能保证一致性。
阶段 1:准备阶段(Prepare Phase)

  • 提议者发起提案
    C1是提议者,C1想要发起修改集群中数据的提议,C1需要先和其他客户端C2、C3、C4、C5确认是否可以发起这个提案。
    C1给C2、C3、C4、C5发了条消息表示想要提个提案,编号为 num,C2、C3、C4、C5没有接受过编号更大的提案C1就可以继续提。这个编号用来区分不同的提案,确保每次只处理最新的提案。
  • 接受者回应
    C2、C3、C4、C5是接受者,分别检查自己是否接受过编号更大的提案。假设都没有接受过更大的提案,C2、C3、C4、C5回复并允许C1提议。Paxos 协议只需要大多数人同意就可以继续下去。C1可以进入下一阶段。

阶段 2:提议阶段(Accept Phase)

  • 提议者正式提出提案
    C1得到了大多数的回应,于是正式发出提案:“C1提议修改A1服务器的数据,提案编号为 num。”
    接受者再次回应
    C2、C3、C4、C5收到提案后,检查提案的编号,并确认这个编号是之前同意的编号,于是回复:“同意修改A1服务器的数据”
    由于C2、C3、C4、C5已经同意(大多数原则),C1的提案就算通过了。

  • 最终结果通知
    C1已经得到了大多数的同意,于是他给所有人发消息:“我在修改数据”,此时C1获得了锁,其他用户C2、C3、C4、C5没有获得锁,所以不能修改服务器的数据。
    即使有的用户没有回复,他们也能收到最终的结果,知道要C1要修改数据了。
    通过这两个阶段,Paxos 确保了大多数人的一致意见,即使部分人没能及时参与讨论,也不会影响结果。

三、代码

#include <stdio.h>
#include <pthread.h>#define ACCEPTORS_NUM 5
#define MAJORITY (ACCEPTORS_NUM/2 + 1)typedef struct
{int promised_id;int accepted_id;int accepted_value;
}Acceptor;Acceptor acceptors[ACCEPTORS_NUM];
pthread_mutex_t lock[ACCEPTORS_NUM];//5把锁void Init_Acceptor()
{for (int i = 0; i < ACCEPTORS_NUM; i++){acceptors[i].promised_id = -1;acceptors[i].accepted_id = -1;acceptors[i].accepted_value = -1;pthread_mutex_init(&lock[i], NULL);}
}//Prepare
int Prepare(int acceptor_index, int proposal_id)
{pthread_mutex_lock(&lock[acceptor_index]);//获得锁if (proposal_id > acceptors[acceptor_index].promised_id){acceptors[acceptor_index].promised_id = proposal_id;pthread_mutex_unlock(&lock[acceptor_index]);//释放锁return 1;//获得提议许可}pthread_mutex_unlock(&lock[acceptor_index]);//释放锁return 0;//未获得提议许可
}//Accept
int Accept(int acceptor_index, int proposal_id,int value)
{pthread_mutex_lock(&lock[acceptor_index]);//获得锁if (proposal_id >= acceptors[acceptor_index].promised_id){acceptors[acceptor_index].promised_id = proposal_id;acceptors[acceptor_index].accepted_value = value;pthread_mutex_unlock(&lock[acceptor_index]);//释放锁return 1;//提议成功}pthread_mutex_unlock(&lock[acceptor_index]);//释放锁return 0;//提议失败
}//Proposervoid* Proposer(void* args)
{int proposal_id = *(int*)args;int value = proposal_id * 10;//假设每个提议的值为编号的10倍printf("Proposer value : %d with proposal ID:%d\n",value,proposal_id);int promise_count = 0;//准备阶段,向所有接收者Acceptors发Prepare请求for (int i = 0; i < ACCEPTORS_NUM; i++){if (Prepare(i, proposal_id)) {promise_count++;}}if (promise_count >= MAJORITY){int accept_count = 0;for (int i = 0; i < ACCEPTORS_NUM; i++){if (Accept(i, proposal_id,value)) {accept_count++;}}if (accept_count >= MAJORITY) {printf("Proposal ID:%d accepted with value %d \n",proposal_id,value);}else{printf("Proposal ID:%d failed in accept\n", proposal_id);}}else{printf("Proposal ID:%d failed in prepare\n", proposal_id, value);}return NULL;
}int main()
{Init_Acceptor();pthread_t proposer1, proposer2;int proposer1_id = 1;int proposer2_id = 2;pthread_create(&proposer1, NULL, Proposer, &proposer1_id);pthread_create(&proposer2, NULL, Proposer, &proposer2_id);pthread_join(proposer1, NULL);pthread_join(proposer2, NULL);return 0;
}

四、运行结果


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

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

相关文章

操作系统_MPI程序设计

一、实验环境搭建 本次MPI集群环境是在电脑中安装mpi的sdk和应用程序后在visual studio 2022 上配置MPI环境。VC++目录---》包含目录---》添加MPI的include目录VC++目录---》库目录---》添加MPI的x64目录VC++目录---》预编译器---》输入“MPICH_SKIP_MPICXX”点击确认。VC++目录…

session测试

jsp1 <%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head><meta charset="UTF-8"><title>session测试</title> </…

704.二分查找

题目 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。示例 1:输入: nums = [-1,0,3,5,9,12], target = 9 输出: 4 解释: 9 出现在 nums 中并且下标为 4 示例 2:输入: nums = [-…

win11微软拼音输入法变繁体字

0. 设置→时间和语言 1. 时间和语言→语言和区域2. 中文简体→语言选项3. 键盘→微软拼音→键盘选项4. 常规5. 选择字符集→简体中文

泰山学堂选拔游记

泰山学堂选拔游记 前言:由于相关保密协议,所有与选拔试题与详细细节有关的内容将被剔除。 Tips:由于神秘因素,我在中学阶段的各个平台部分文章与笔记已经进行了隐藏。 插曲:等通知大学的经典通知方式 通过笔试后,要加对应取向面试群了解消息,但各个取向过笔试预留加面试…

mongo基本命令(一)

一 前言 环境: win10 mongo6.0.1 记录一些基本的mongo查询命令 二 查询命令 1 进入命令行 进入mongo命令行,我这里是mongo是装在docker里面的 需要先在docker里面启动mongo容器 docker exec -it xxx bash 进入mongo容器,xxx为mongo容器名 mongosh 进入mongo命令行,我安装…

Java21虚拟线程:我的锁去哪儿了?

0 前言 最近的文章中,我们详细介绍了当我们迁移到 Java 21 并将代际 ZGC 作为默认垃圾收集器时,我们的工作负载是如何受益的。虚拟线程是我们在这次迁移中兴奋采用的另一个特性。 对虚拟线程新手,它们被描述为“轻量级线程,大大减少编写、维护和观察高吞吐量并发应用程序的…