首页 > 其他分享 >操作系统_Paxos协议实现数据一致性更新

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

时间:2024-10-19 23:33:17浏览次数:8  
标签:操作系统 int pthread 一致性 C1 proposal Paxos id acceptor

一、实验环境

系统: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;//提议失败
}

//Proposer

void* 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;
}

四、运行结果


标签:操作系统,int,pthread,一致性,C1,proposal,Paxos,id,acceptor
From: https://www.cnblogs.com/loremmoqi/p/18486728

相关文章

  • 操作系统_MPI程序设计
    一、实验环境搭建本次MPI集群环境是在电脑中安装mpi的sdk和应用程序后在visualstudio2022上配置MPI环境。VC++目录---》包含目录---》添加MPI的include目录VC++目录---》库目录---》添加MPI的x64目录VC++目录---》预编译器---》输入“MPICH_SKIP_MPICXX”点击确认。V......
  • 30天自制操作系统(一)启动区
    一、启动区 ORG 0x7C00 JMP entry DB 0x90 DB "HELLOIPL" DW 512 DB 1 DW 1 DB 2 DW 224 DW 2880 DB 0xf0 DW 9 DW 18 DW 2 DD 0 DD 2880 DB 0,0,0x29 DD 0xffffffff DB "HELLO-OS" DB "FAT12" RESB......
  • 操作系统(6) (Named /Unnamed Semaphore信号量详解)
    目录1:信号量的基本概念2:命名信号量的示例代码3.无名信号量(UnnamedSemaphore)背景(Background)示例代码讲解初始化无名信号量线程函数创建线程并等待完成销毁信号量总结4.对比1:信号量的基本概念背景介绍:信号量是一种并发编程中的同步原语,它用于协调多......
  • 【rCore OS 开源操作系统】Rust 智能指针
    前置知识点何为“智能”在Rust中,“智能指针”是指那些实现了特定智能行为的指针类型。这些智能行为通常包括内存管理、生命周期跟踪以及所有权转移等。常见智能指针BoxBox<T>是Rust中最简单的智能指针类型之一,它用于堆分配的内存。Box<T>允许你在堆上分配类型T......
  • 专题二:操作系统基本原理
    1.操作系统概述操作系统:管理系统的硬件、软件、数据资源控制程序运行人机之间的接口应用软件与硬件之间的接口进程管理存储管理文件管理作业管理设备管理2.进程管理2.1.进程状态(三态模型、五态模型)2.2.★★★信号量与PV操作★★★2.2.1.前趋图2.2.2.进程......
  • 记录Redis+MQ延迟双删保证缓存一致性
    场景描述在博客系统中,用户可以给博客点赞或者评论,这些操作需要更新数据库中的数据,同时要保证缓存中的博客信息与数据库保持一致。为了提高性能,博客数据会存放在Redis缓存中。但当有大量用户同事点赞或是评论时,缓存和数据库中的数据可能出现不一致。何谓延迟双删?延迟双删......
  • 【哈工大_操作系统实验】Lab5 基于内核栈切换的进程切换
    本节将更新哈工大《操作系统》课程第五个Lab实验基于内核栈切换的进程切换。按照实验书要求,介绍了非常详细的实验操作流程,并提供了超级无敌详细的代码注释。Linux0.11采用TSS和一条指令完成任务切换,虽然简单但执行时间长。堆栈实现任务切换更快,且可以使用指令流水......
  • Free RTOS实时操作系统
    FreeRTOS实时操作系统目录FreeRTOS实时操作系统裸机和实时操作系统嵌入式操作系统的作用向裸机工程中添加FreeRTOS源码修改FreeRTOSConfig.h文件(操作系统的配置文件)--修改stm32f10x_it.c创建任务–动态内存FreeRTOS文件夹介绍更改过后的代码裸机和实时......
  • Java实现数据一致性
    在分布式系统中,数据一致性是一个核心问题。数据一致性确保了系统在并发操作和网络分区等情况下,数据的准确性和可靠性。Java作为一种广泛使用的编程语言,提供了多种机制来实现数据一致性。本文将探讨Java中实现数据一致性的方法和技术。1.数据一致性的定义在分布式系统中,数据......
  • 操作系统层面有哪些锁
    操作系统层面有哪些锁互斥锁互斥锁在同一时刻只允许一个线程或进程访问共享资源,其他线程或进程需要等待锁的释放。同步锁两个或两个以上的进程或线程在运行过程中协同步调,按预定的先后次序运行。比如A任务的运行依赖于B任务产生的数据互斥与同步的区别​ 互斥锁是通......