分佈式一致性算法Paxos JAVA多線程方式實現

github地址:

https://github.com/hellolinjx/PaxosImpl/


//	準備提案過程,獲得大多數決策者支持後進入確認提案階段。
	public synchronized boolean prepare(){
		PrepareResult prepareResult = null;
		
		boolean isContinue = true;
		//	已獲得承諾個數
		int promisedCount = 0;
		
		do{
			List<Proposal> promisedProposals = new ArrayList<Proposal>(); 
			List<Proposal> acceptedProposals = new ArrayList<Proposal>();
			promisedCount = 0;
			for	(Acceptor acceptor : acceptors){
				
				prepareResult = acceptor.onPrepare(proposal);
				//	隨機休眠一段時間,模擬網絡延遲。
				PaxosUtil.sleepRandom();
				
				//	模擬網絡異常
				if	(null==prepareResult){
					continue;
				}
				
				//	獲得承諾
				if	(prepareResult.isPromised()){
					promisedCount ++;
				}else{
					//	決策者已經給了更高id題案的承諾
					if	(prepareResult.getAcceptorStatus()==AcceptorStatus.PROMISED){
						promisedProposals.add(prepareResult.getProposal());
					}
					//	決策者已經通過了一個題案
					if	(prepareResult.getAcceptorStatus()==AcceptorStatus.ACCEPTED){
						acceptedProposals.add(prepareResult.getProposal());
					}
				}
			}// end of for
			
			//	獲得多數決策者的承諾
			//	可以進行第二階段:題案提交
			if	(promisedCount >= halfCount){
				break;
			}
			Proposal votedProposal = votedEnd(acceptedProposals);
			//	決策者已經半數通過題案
			if	(votedProposal !=null){
				System.out.println("決策已經投票結束:" + votedProposal);
				return true;
			}
			
			
			Proposal maxIdAcceptedProposal = getMaxIdProposal(acceptedProposals);
			//	在已經被決策者通過題案中選擇序列號最大的決策,作爲自己的決策。
			if	(maxIdAcceptedProposal != null){
				proposal.setId(PaxosUtil.generateId());
				proposal.setValue(maxIdAcceptedProposal.getValue());
			}else{
				proposal.setId(PaxosUtil.generateId());
			}
			
			
		}while(isContinue);
		return false;
	}
	
	//	獲得大多數決策者承諾後,開始進行提案確認
	public synchronized boolean commit(){ 
		boolean isContinue = true;
		
		//	已獲得接受該提案的決策者個數
		int acceptedCount = 0;
		do{
			List<Proposal> acceptedProposals = new ArrayList<Proposal>();
			acceptedCount = 0;
			for	(Acceptor acceptor : acceptors){
	
				CommitResult commitResult = acceptor.onCommit(proposal);
				//	模擬網絡延遲
				PaxosUtil.sleepRandom();
				
				//	模擬網絡異常
				if	(null==commitResult){
					continue;
				}
				
				//	題案被決策者接受。
				if	(commitResult.isAccepted()){
					acceptedCount ++;
				}else{
					acceptedProposals.add(commitResult.getProposal());
				}
			}
			
			//	題案被半數以上決策者接受,說明題案已經被選出來。
			if	(acceptedCount >= halfCount){
				System.out.println("題案已經投票選出:" + proposal);
				return true;
			}else{
				Proposal maxIdAcceptedProposal = getMaxIdProposal(acceptedProposals);
				//	在已經被決策者通過題案中選擇序列號最大的決策,重新生成遞增id,改變自己的value爲序列號最大的value。
				//	這是一種預測,預測此maxIdAccecptedProposal最有可能被超過半數的決策者接受。
				if	(maxIdAcceptedProposal != null){
					proposal.setId(PaxosUtil.generateId());
					proposal.setValue(maxIdAcceptedProposal.getValue());
				}else{
					proposal.setId(PaxosUtil.generateId());
				}
				
				//	回退到決策準備階段
				if	(prepare())
					return true;
			}
			
		}while(isContinue);
		
		return true;
	}

//	加鎖此準備函數,不允許同時訪問。模擬單個決策者串行處理一個請求。
	public synchronized PrepareResult onPrepare(Proposal szProposal){
		PrepareResult prepareResult = new PrepareResult();
		
		//	模擬網絡不正常,發生丟包、超時現象
		if	(PaxosUtil.isCrashed()){
			PaxosUtil.printStr("Network not normal: " + this.toString());
			return null;
		}
		
		switch (status){
			//	NONE表示之前沒有承諾過任何提議者
			//	此時,接受提案
			case NONE:
				prepareResult.setAcceptorStatus(AcceptorStatus.NONE);
				prepareResult.setPromised(true);
				prepareResult.setProposal(null);
				//	轉換自身的狀態,已經承諾了提議者,並記錄承諾的提案。
				status = AcceptorStatus.PROMISED;
				promisedProposal.copyFromInstance(szProposal);
				return prepareResult;
			//	已經承諾過任意提議者
			case PROMISED:
				//	判斷提案的先後順序,只承諾相對較新的提案
				if	(promisedProposal.getId() > szProposal.getId()){
					prepareResult.setAcceptorStatus(status);
					prepareResult.setPromised(false);
					prepareResult.setProposal(promisedProposal);
					return prepareResult;
				}else{
					promisedProposal.copyFromInstance(szProposal);
					prepareResult.setAcceptorStatus(status);
					prepareResult.setPromised(true);
					prepareResult.setProposal(promisedProposal);
					return prepareResult;
				}
			//	已經批准過提案
			case ACCEPTED:
				//	如果是同一個提案,只是序列號增大
				//	批准提案,更新序列號。
				if	(promisedProposal.getId()<szProposal.getId()
						&& promisedProposal.getValue().equals(szProposal.getValue())){
					promisedProposal.setId(szProposal.getId());
					prepareResult.setAcceptorStatus(status);
					prepareResult.setPromised(true);
					prepareResult.setProposal(promisedProposal);
					return prepareResult;
				}else{ 	//	否則,不予批准
					prepareResult.setAcceptorStatus(status);
					prepareResult.setPromised(false);
					prepareResult.setProposal(acceptedProposal);
					return prepareResult;
				}
			default:
				//return null;
		}
		
		return null;
	}
	
	//	加鎖此提交函數,不允許同時訪問,模擬單個決策者串行決策
	public synchronized CommitResult onCommit(Proposal szProposal){
		CommitResult commitResult = new CommitResult();
		if	(PaxosUtil.isCrashed()){
			return null;
		}
		switch (status){
			//	不可能存在此狀態
			case NONE:	return null;
			//	已經承諾過提案
			case PROMISED:
				//	判斷commit提案和承諾提案的序列號大小
				//	大於,接受提案。
				if	(szProposal.getId() >= promisedProposal.getId()){
					promisedProposal.copyFromInstance(szProposal);
					acceptedProposal.copyFromInstance(szProposal);
					status = AcceptorStatus.ACCEPTED;
					commitResult.setAccepted(true);
					commitResult.setAcceptorStatus(status);
					commitResult.setProposal(promisedProposal);
					return commitResult;
					
				}else{	//	小於,回絕提案
					commitResult.setAccepted(false);
					commitResult.setAcceptorStatus(status);
					commitResult.setProposal(promisedProposal);
					return commitResult;
				}
			//	已接受過提案
			case ACCEPTED:
				//	同一提案,序列號較大,接受
				if	(szProposal.getId() > acceptedProposal.getId()
						&& szProposal.getValue().equals(acceptedProposal.getValue())){
					acceptedProposal.setId(szProposal.getId());
					commitResult.setAccepted(true);
					commitResult.setAcceptorStatus(status);
					commitResult.setProposal(acceptedProposal);
					return commitResult;
				}else{	//	否則,回絕提案
					commitResult.setAccepted(false);
					commitResult.setAcceptorStatus(status);
					commitResult.setProposal(acceptedProposal);
					return commitResult;
				}
		}
		
		
		return null;
	}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章