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