中文字幕人妻中文_99精品欧美一区二区三区综合在线_精品久久久久一区二区_色月丁香_免费福利在线视频_欧美大片免费观看网址_国产伦精品一区二区三区在线播放_污污污污污污www网站免费_久久月本道色综合久久_色69激情爱久久_尹人香蕉久久99天天拍_国产美女www_亚洲国产精品无码7777一线_五月婷婷六月激情_看免费一级片_精品久久久久久成人av_在线色亚洲_女人另类性混交zo_国产精品青青在线观看爽香蕉_人人澡人人添人人爽一区二区

主頁 > 知識庫 > 詳解分布式系統中如何用python實現Paxos

詳解分布式系統中如何用python實現Paxos

熱門標簽:沈陽外呼系統呼叫系統 外呼系統哪些好辦 如何申請400電話費用 武漢外呼系統平臺 江西省地圖標注 富錦商家地圖標注 沈陽人工外呼系統價格 沈陽防封電銷卡品牌 池州外呼調研線路

一致性算法背景

1.Paxos一致性算法解決的問題:分布式系統中數據不能存在單個節點(主機)上,否則可能出現單點故障;多個節點(主機)需要保證具有相同的數據。

2.什么是一致性:一致性就是數據保持一致,在分布式系統中,可以理解為多個節點中數據的值是一致的。

3.一致性模型分類:一般分為強一致性和弱一致性,強一致性保證系統改變提交以后立即改變集群的狀態。常見模型包括:Paxos,Raft(muti-paxos),ZAB(muti-paxos); 弱一致性也叫最終一致性,系統不保證改變提交以后立即改變集群的狀態,但是隨著時間的推移最終狀態一致的。常見模型包括:DNS系統,Gossip協議

4.一致性算法使用案例:Google的Chubby分布式鎖服務,采用了Paxos算法;etcd分布式鍵值數據庫,采用了Raft算法;ZooKeeper分布式應用協調服務以及Chubby的開源實現,采用ZAB算法

simple-paxos就單個靜態值達一致性本身并不實用,我們需要實現的集群系統(銀行賬戶服務)希望就隨時間變化的特定狀態(賬戶余額)達成一致。所以需要使用Paxos就每個操作達成一致,將每個修改視為狀態機轉換。

Multi-Paxos實際上是simple Paxos實例(插槽)的序列,每個實例都按順序編號。每個狀態轉換都被賦予一個“插槽編號”,集群的每個成員都以嚴格的數字順序執行轉換。為了更改群集的狀態(例如,處理傳輸操作),我們嘗試在下一個插槽中就該操作達成一致性。具體來說,這意味著向每個消息添加一個插槽編號,并在每個插槽的基礎上跟蹤所有協議狀態。

為每個插槽運行Paxos,至少兩次往返會太慢。Multi-Paxos通過對所有插槽使用相同的選票編號集進行優化,并同時對所有插槽執行Prepare/Promise。

Client   Proposer      Acceptor     Learner

   |         |          |  |  |       |  | --- First Request ---

   X-------->|          |  |  |       |  |  Request

   |         X--------->|->|->|       |  |  Prepare(N)

   |         |---------X--X--X       |  |  Promise(N,I,{Va,Vb,Vc})

   |         X--------->|->|->|       |  |  Accept!(N,I,V)

   |         |---------X--X--X------>|->|  Accepted(N,I,V)

   |---------------------------------X--X  Response

   |         |          |  |  |       |  |

Paxos實現

在實用軟件中實現Multi-Paxos是出了名的困難,催生了許多論文如"Paxos Made Simple",“Paxos Made Practical”

首先,multi-poposer在繁忙的環境中可能會成為問題,因為每個群集成員都試圖在每個插槽中決定其狀態機操作。解決方法是選舉一名“leader”,負責為每個時段提交選票。所有其他群集節點將新操作發送到領導者執行。因此,在只有一名領導人的正常運作中,不會發生投票沖突。

Prepare/Promise階段可以作為一種leader選舉:無論哪個集群成員擁有最近承諾的選票號碼,都被視為leader。leader后續可以自由地直接執行Accept/Accepted階段,而不重復第一階段。我們將在下文看到的,leader選舉實際上是相當復雜的。

雖然simple Paxos保證集群不會達成沖突的決定,但它不能保證會做出任何決定。例如,如果初始的Prepare消息丟失,并且沒有到達接受者,則提議者將等待永遠不會到達的Promise消息。解決這個問題需要精心設計的重新傳輸:足以最終取得進展,但不會群集產生數據包風暴。

另一個問題是決定的傳播。在正常情況下,簡單地廣播Decision信息就可以解決這個問題。但是,如果消息丟失,節點可能會永遠不知道該決定,并且無法為以后的插槽應用狀態機轉換。所以實現需要一些機制來共享有關已決定提案的信息。

使用分布式狀態機帶來了另一個挑戰:當新節點啟動時,它需要獲取群集的現有狀態。
雖然可以通過趕上第一個插槽以來的所有插槽的決策來做到這一點,但在一個大的集群中,這可能涉及數百萬個插槽。此外,我們需要一些方法來初始化一個新的群集。

集群庫介紹

前面都是理論介紹,下面我們使用python來實現一個簡化的Multi-Paxos

業務場景和痛點

我們以簡單的銀行賬戶管理服務的場景作為案例。在這個服務中,每一個賬戶都有一個當前余額,同時每個賬戶都有自己的賬號。用戶可以對賬戶進行“存款”、“轉賬”、“查詢當前余額”等操作。“轉賬”操作同時涉及了兩個賬戶:轉出賬戶和轉入賬戶,如果賬戶余額不足,轉賬操作必須被駁回。

如果這個服務僅僅在一個服務器上部署,很容易就能夠實現:使用一個操作鎖來確保“轉賬”操作不會同時進行,同時對轉出賬戶的進行校驗。然而,銀行不可能僅僅依賴于一個服務器來儲存賬戶余額這樣的關鍵信息,通常,這些服務都是被分布在多個服務器上的,每一個服務器各自運行著相同代碼的實例。用戶可以通過任何一個服務器來操作賬戶。

在一個簡單的分布式處理系統的實現中,每個服務器都會保存一份賬戶余額的副本。它會處理任何收到的操作,并且將賬戶余額的更新發送給其他的服務器。但是這種方法有一個嚴重的問題:如果兩個服務器同時對一個賬戶進行操作,哪一個新的賬戶余額是正確的?即使服務器不共享余額而是共享操作,對一個賬戶同時進行轉賬操作也可能造成透支。

從根本上來說,這些錯誤的發生都是由于服務器使用它們本地狀態來響應操作,而不是首先確保本地狀態與其他服務器相匹配。比如,想象服務器A接到了從賬號101向賬號202轉賬的操作指令,而此時服務器B已經處理了另一個把賬號101的錢都轉到賬號202的請求,卻沒有通知服務器A。這樣,服務器A的本地狀態與服務器B不一樣,即使會造成賬戶101透支,服務器A依然允許從賬號101進行轉賬操作。

分布式狀態機

為了防止上述情況發生我們采用了一種叫做“分布式狀態機”的工具。它的思路是對每個同樣的輸入,每個服務器都運行同樣的對應的狀態機。由于狀態機的特性,對于同樣的輸入每個服務器的輸出都是一樣的。對于像“轉賬”、“查詢當前余額”等操作,賬號和余額也都是狀態機的輸入。

這個應用的狀態機比較簡單:

def execute_operation(state, operation):
     if operation.name == 'deposit':
         if not verify_signature(operation.deposit_signature):
         return state, False
         state.accounts[operation.destination_account] += operation.amount
         return state, True
     elif operation.name == 'transfer':
         if state.accounts[operation.source_account]  operation.amount:
             return state, False
             state.accounts[operation.source_account] -= operation.amount
         state.accounts[operation.destination_account] += operation.amount
         return state, True
     elif operation.name == 'get-balance':
     return state, state.accounts[operation.account]

值得注意的是,運行“查詢當前余額”操作時雖然并不會改變當前狀態,但是我們依然把它當做一個狀態變化操作來實現。這確保了返回的余額是分布式系統中的最新信息,并且不是基于一個服務器上的本地狀態來進行返回的。

這可能跟你在計算機課程中學習到的典型的狀態機不太一樣。傳統的狀態機是一系列有限個狀態的集合,每個狀態都與一個標記的轉移行為相對應,而在本文中,狀態機的狀態是賬戶余額的集合,因此存在無窮多個可能的狀態。但是,狀態機的基本規則同樣適用于本文的狀態機:對于同樣的初始狀態,同樣的輸入總是有同樣的輸出。

因此,分布式狀態機確保了對于同樣的操作,每個主機都會有同樣的相應。但是,為了確保每個服務器都允許狀態機的輸入,前文中提到的問題依然存在。這是一個一致性問題,為了解決它我們采用了一種派生的Paxos算法。

核心需求

可以為較大的應用程序提供一致性服務: 我們用一個Cluster庫來實現簡化的Multi-Paxos正確性是這個庫最重要的能力,因此結構化代碼是很重要的,以便我們可以看到并測試它與規范的對應關系。復雜的協議可能會出現復雜的故障,因此我們將構建對復現和調試不常見的故障的支持。我們會實現POC代碼:足以證明核心概念是實用的,代碼的結構化是為了后續添加此功能對核心實現的更改最小
我們開始coding吧。

類型和常量

cluster中的協議需要使用15不同的消息類型,每種消息類型使用collection中的namedturple定義:

Accepted = namedtuple('Accepted', ['slot', 'ballot_num'])
    Accept = namedtuple('Accept', ['slot', 'ballot_num', 'proposal'])
    Decision = namedtuple('Decision', ['slot', 'proposal'])
    Invoked = namedtuple('Invoked', ['client_id', 'output'])
    Invoke = namedtuple('Invoke', ['caller', 'client_id', 'input_value'])
    Join = namedtuple('Join', [])
    Active = namedtuple('Active', [])
    Prepare = namedtuple('Prepare', ['ballot_num'])
    Promise = namedtuple('Promise', ['ballot_num', 'accepted_proposals'])
    Propose = namedtuple('Propose', ['slot', 'proposal'])
    Welcome = namedtuple('Welcome', ['state', 'slot', 'decisions'])
    Decided = namedtuple('Decided', ['slot'])
    Preempted = namedtuple('Preempted', ['slot', 'preempted_by'])
    Adopted = namedtuple('Adopted', ['ballot_num', 'accepted_proposals'])
    Accepting = namedtuple('Accepting', ['leader'])

使用命名元組描述每種消息類型可以保持代碼的clean,并有助于避免一些簡單的錯誤。如果命名元組構造函數沒有被賦予正確的屬性,則它將引發異常,從而使錯誤變得明顯。元組在日志消息中k可以很好地格式化,不會像字典那樣使用那么多的內存。

創建消息:

msg = Accepted(slot=10, ballot_num=30)

訪問消息:

got_ballot_num = msg.ballot_num

后面我們會了解這些消息的含義。
代碼還引入了一些常量,其中大多數常量定義了各種消息的超時:

JOIN_RETRANSMIT = 0.7
    CATCHUP_INTERVAL = 0.6
    ACCEPT_RETRANSMIT = 1.0
    PREPARE_RETRANSMIT = 1.0
    INVOKE_RETRANSMIT = 0.5
    LEADER_TIMEOUT = 1.0
    NULL_BALLOT = Ballot(-1, -1)  # sorts before all real ballots
    NOOP_PROPOSAL = Proposal(None, None, None)  # no-op to fill otherwise empty slots

最后我們需要定義協議中的Proposal和Ballot

Proposal = namedtuple('Proposal', ['caller', 'client_id', 'input'])
    Ballot = namedtuple('Ballot', ['n', 'leader'])

組件模型

實現multi-paxos的核心組件包括Role和Node。

為了保證可測試性并保持代碼的可讀性,我們將Cluster分解為與協議中描述的角色相對應的幾個類。每個都是Role的子類。

class Role(object):

    def __init__(self, node):
        self.node = node
        self.node.register(self)
        self.running = True
        self.logger = node.logger.getChild(type(self).__name__)

    def set_timer(self, seconds, callback):
        return self.node.network.set_timer(self.node.address, seconds,
                                           lambda: self.running and callback())

    def stop(self):
        self.running = False
        self.node.unregister(self)

群集節點的角色由Node類粘在一起,該類代表網絡上的單個節點。在程序過程中角色將添加到節點中,并從節點中刪除。

到達節點的消息將中繼到所有活動角色,調用以消息類型命名的方法,前綴為do_。 這些do_方法接收消息的屬性作為關鍵字參數,以便于訪問。Node``類還提供了``send方法作為方便,使用functools.partial為Network類的相同方法提供一些參數。

class Node(object):
    unique_ids = itertools.count()

    def __init__(self, network, address):
        self.network = network
        self.address = address or 'N%d' % self.unique_ids.next()
        self.logger = SimTimeLogger(
            logging.getLogger(self.address), {'network': self.network})
        self.logger.info('starting')
        self.roles = []
        self.send = functools.partial(self.network.send, self)

    def register(self, roles):
        self.roles.append(roles)

    def unregister(self, roles):
        self.roles.remove(roles)

    def receive(self, sender, message):
        handler_name = 'do_%s' % type(message).__name__

        for comp in self.roles[:]:
            if not hasattr(comp, handler_name):
                continue
            comp.logger.debug("received %s from %s", message, sender)
            fn = getattr(comp, handler_name)
            fn(sender=sender, **message._asdict())

應用接口

每個集群成員上都會創建并啟動一個Member對象,提供特定于應用程序的狀態機和對等項列表。如果成員對象正在加入現有集群,則該成員對象向該節點添加bootstrap角色,如果正在創建新集群,則該成員對象添加seed。再用Network.run在單獨的線程中運行協議。

應用程序通過該invoke方法與集群進行交互,從而啟動了狀態轉換, 確定該提議并運行狀態機后,invoke將返回狀態機的輸出。該方法使用簡單的同步Queue來等待協議線程的結果。

class Member(object):

    def __init__(self, state_machine, network, peers, seed=None,
                 seed_cls=Seed, bootstrap_cls=Bootstrap):
        self.network = network
        self.node = network.new_node()
        if seed is not None:
            self.startup_role = seed_cls(self.node, initial_state=seed, peers=peers,
                                      execute_fn=state_machine)
        else:
            self.startup_role = bootstrap_cls(self.node,
                                      execute_fn=state_machine, peers=peers)
        self.requester = None

    def start(self):
        self.startup_role.start()
        self.thread = threading.Thread(target=self.network.run)
        self.thread.start()

    def invoke(self, input_value, request_cls=Requester):
        assert self.requester is None
        q = Queue.Queue()
        self.requester = request_cls(self.node, input_value, q.put)
        self.requester.start()
        output = q.get()
        self.requester = None
        return output

Role 類

Paxos協議中的角色包括:client, acceptor, proposer, learner, and leader。在典型的實現中,單個processor可以同時扮演一個或多個角色。這不會影響協議的正確性,通常會合并角色以改善協議中的延遲和/或消息數量。

下面逐一實現每個角色類

Acceptor

Acceptor 類實現的是Paxos中的 acceptor角色,所以必須存儲最近promise的選票編號,以及每個時段接受的各個slot的proposal,同時需要相應Prepare和Accept消息。 這里的POC實現是一個和協議可以直接對應的短類,對于acceptor來說Multi-paxos看起來像是簡單的Paxos,只是在message中添加了slot number。

class Acceptor(Role):

    def __init__(self, node):
        super(Acceptor, self).__init__(node)
        self.ballot_num = NULL_BALLOT
        self.accepted_proposals = {}  # {slot: (ballot_num, proposal)}

    def do_Prepare(self, sender, ballot_num):
        if ballot_num > self.ballot_num:
            self.ballot_num = ballot_num
            # we've heard from a scout, so it might be the next leader
            self.node.send([self.node.address], Accepting(leader=sender))

        self.node.send([sender], Promise(
            ballot_num=self.ballot_num, 
            accepted_proposals=self.accepted_proposals
        ))

    def do_Accept(self, sender, ballot_num, slot, proposal):
        if ballot_num >= self.ballot_num:
            self.ballot_num = ballot_num
            acc = self.accepted_proposals
            if slot not in acc or acc[slot][0]  ballot_num:
                acc[slot] = (ballot_num, proposal)

        self.node.send([sender], Accepted(
            slot=slot, ballot_num=self.ballot_num))

Replica

Replica類是Role類最復雜的子類,對應協議中的Learner和Proposal角色,它的主要職責是:提出新的proposal;在決定proposal時調用本地狀態機;跟蹤當前Leader;以及將新啟動的節點添加到集群中。

Replica創建新的proposal以響應來自客戶端的“invoke”消息,選擇它認為是未使用的插槽,并向當前leader發送“Propose”消息。如果選定插槽的共識是針對不同proposal,則replica必須使用新插槽re-propose。

下圖顯示Replica的角色控制流程:

Requester    Local Rep   Current Leader

   X---------->|             |    Invoke

   |           X------------>|    Propose

   |           |------------X    Decision

   |----------X             |    Decision

   |           |             |

Decision消息表示集群已達成共識的插槽, Replica類存儲新的決定并運行狀態機,直到到達未確定的插槽。Replica從本地狀態機已處理的提交的slot識別出集群已同意的已決定的slot。如果slot出現亂序,提交的提案可能會滯后,等待下一個空位被決定。提交slot后,每個replica會將操作結果發送回一條Invoked消息給請求者。

在某些情況下slot可能沒有有效的提案,也沒有決策,需要狀態機一個接一個地執行slot,因此群集必須就填充slot的內容達成共識。為了避免這種可能性,Replica在遇到插槽時會提出“no-op”的proposal。如果最終決定了這樣的proposal,則狀態機對該slot不執行任何操作。

同樣,同一proposal有可能被Decision兩次。對于任何此類重復的proposal,Replica將跳過調用狀態機,而不會對該slot執行任何狀態轉換。

Replicas需要知道哪個節點是active leader才能向其發送Propose消息, 要實現這一目標,每個副本都使用三個信息源跟蹤active leader。

當leader 的角色轉換為active時,它會向同一節點上的副本發送一條Adopted消息(下圖):

Leader    Local Repplica   

   X----------->|          Admopted

當acceptor角色向Promise新的leader發送Accepting消息時,它將消息發送到其本地副本(下圖)。

Acceptor    Local Repplica   

   X----------->|          Accepting

active leader將以心跳的形式發送Active消息。如果在LEADER_TIMEOUT到期之前沒有此類消息到達,則Replica將假定該Leader已死,并轉向下一個Leader。在這種情況下,重要的是所有副本都選擇相同的新領導者,我們可以通過對成員進行排序并在列表中選擇下一個leader。

當節點加入網絡時,Bootstrap將發送一條Join消息(下圖)。Replica以一條Welcome包含其最新狀態的消息作為響應,從而使新節點能夠快速啟用。

BootStrap     Replica        Replica       Replica
     X---------->|             |             |    Join
     |----------X             X             |    Welcome
     X------------------------>|             |    Join
     |------------------------X             |    Welcome
     X-------------------------------------->|    Join
     |--------------------------------------X    Welcome      
class Replica(Role):

    def __init__(self, node, execute_fn, state, slot, decisions, peers):
        super(Replica, self).__init__(node)
        self.execute_fn = execute_fn
        self.state = state
        self.slot = slot
        self.decisions = decisions
        self.peers = peers
        self.proposals = {}
        # next slot num for a proposal (may lead slot)
        self.next_slot = slot
        self.latest_leader = None
        self.latest_leader_timeout = None

    # making proposals

    def do_Invoke(self, sender, caller, client_id, input_value):
        proposal = Proposal(caller, client_id, input_value)
        slot = next((s for s, p in self.proposals.iteritems() if p == proposal), None)
        # propose, or re-propose if this proposal already has a slot
        self.propose(proposal, slot)

    def propose(self, proposal, slot=None):
        """Send (or resend, if slot is specified) a proposal to the leader"""
        if not slot:
            slot, self.next_slot = self.next_slot, self.next_slot + 1
        self.proposals[slot] = proposal
        # find a leader we think is working - either the latest we know of, or
        # ourselves (which may trigger a scout to make us the leader)
        leader = self.latest_leader or self.node.address
        self.logger.info(
            "proposing %s at slot %d to leader %s" % (proposal, slot, leader))
        self.node.send([leader], Propose(slot=slot, proposal=proposal))

    # handling decided proposals

    def do_Decision(self, sender, slot, proposal):
        assert not self.decisions.get(self.slot, None), \

                "next slot to commit is already decided"
        if slot in self.decisions:
            assert self.decisions[slot] == proposal, \

                "slot %d already decided with %r!" % (slot, self.decisions[slot])
            return
        self.decisions[slot] = proposal
        self.next_slot = max(self.next_slot, slot + 1)

        # re-propose our proposal in a new slot if it lost its slot and wasn't a no-op
        our_proposal = self.proposals.get(slot)
        if (our_proposal is not None and 
            our_proposal != proposal and our_proposal.caller):
            self.propose(our_proposal)

        # execute any pending, decided proposals
        while True:
            commit_proposal = self.decisions.get(self.slot)
            if not commit_proposal:
                break  # not decided yet
            commit_slot, self.slot = self.slot, self.slot + 1

            self.commit(commit_slot, commit_proposal)

    def commit(self, slot, proposal):
        """Actually commit a proposal that is decided and in sequence"""
        decided_proposals = [p for s, p in self.decisions.iteritems() if s  slot]
        if proposal in decided_proposals:
            self.logger.info(
                "not committing duplicate proposal %r, slot %d", proposal, slot)
            return  # duplicate

        self.logger.info("committing %r at slot %d" % (proposal, slot))
        if proposal.caller is not None:
            # perform a client operation
            self.state, output = self.execute_fn(self.state, proposal.input)
            self.node.send([proposal.caller], 
                Invoked(client_id=proposal.client_id, output=output))

    # tracking the leader

    def do_Adopted(self, sender, ballot_num, accepted_proposals):
        self.latest_leader = self.node.address
        self.leader_alive()

    def do_Accepting(self, sender, leader):
        self.latest_leader = leader
        self.leader_alive()

    def do_Active(self, sender):
        if sender != self.latest_leader:
            return
        self.leader_alive()

    def leader_alive(self):
        if self.latest_leader_timeout:
            self.latest_leader_timeout.cancel()

        def reset_leader():
            idx = self.peers.index(self.latest_leader)
            self.latest_leader = self.peers[(idx + 1) % len(self.peers)]
            self.logger.debug("leader timed out; tring the next one, %s", 
                self.latest_leader)
        self.latest_leader_timeout = self.set_timer(LEADER_TIMEOUT, reset_leader)

    # adding new cluster members

    def do_Join(self, sender):
        if sender in self.peers:
            self.node.send([sender], Welcome(
                state=self.state, slot=self.slot, decisions=self.decisions))

Leader Scout Commander

Leader的主要任務是接受Propose要求新投票的消息并做出決定。成功完成協議的Prepare/Promise部分后Leader將處于“Active狀態” 。活躍的Leader可以立即發送Accept消息以響應Propose。

與按角色分類的模型保持一致,Leader會委派scout和Commander角色來執行協議的每個部分。

class Leader(Role):

    def __init__(self, node, peers, commander_cls=Commander, scout_cls=Scout):
        super(Leader, self).__init__(node)
        self.ballot_num = Ballot(0, node.address)
        self.active = False
        self.proposals = {}
        self.commander_cls = commander_cls
        self.scout_cls = scout_cls
        self.scouting = False
        self.peers = peers

    def start(self):
        # reminder others we're active before LEADER_TIMEOUT expires
        def active():
            if self.active:
                self.node.send(self.peers, Active())
            self.set_timer(LEADER_TIMEOUT / 2.0, active)
        active()

    def spawn_scout(self):
        assert not self.scouting
        self.scouting = True
        self.scout_cls(self.node, self.ballot_num, self.peers).start()

    def do_Adopted(self, sender, ballot_num, accepted_proposals):
        self.scouting = False
        self.proposals.update(accepted_proposals)
        # note that we don't re-spawn commanders here; if there are undecided
        # proposals, the replicas will re-propose
        self.logger.info("leader becoming active")
        self.active = True

    def spawn_commander(self, ballot_num, slot):
        proposal = self.proposals[slot]
        self.commander_cls(self.node, ballot_num, slot, proposal, self.peers).start()

    def do_Preempted(self, sender, slot, preempted_by):
        if not slot:  # from the scout
            self.scouting = False
        self.logger.info("leader preempted by %s", preempted_by.leader)
        self.active = False
        self.ballot_num = Ballot((preempted_by or self.ballot_num).n + 1, 
                                 self.ballot_num.leader)

    def do_Propose(self, sender, slot, proposal):
        if slot not in self.proposals:
            if self.active:
                self.proposals[slot] = proposal
                self.logger.info("spawning commander for slot %d" % (slot,))
                self.spawn_commander(self.ballot_num, slot)
            else:
                if not self.scouting:
                    self.logger.info("got PROPOSE when not active - scouting")
                    self.spawn_scout()
                else:
                    self.logger.info("got PROPOSE while scouting; ignored")
        else:
            self.logger.info("got PROPOSE for a slot already being proposed")

Leader想要變為活動狀態時會創建一個Scout角色,以響應Propose在其處于非活動狀態時收到消息(下圖),Scout發送(并在必要時重新發送)Prepare消息,并收集Promise響應,直到聽到消息為止。多數同行或直到被搶占為止。在通過Adopted或Preempted回復給Leader。

Leader    Scout      Acceptor     Acceptor    Acceptor

   |          |          |            |           |   

   |          X--------->|            |           |    Prepare

   |          |---------X            |           |    Promise

   |          X---------------------->|           |    Prepare

   |          |----------------------X           |    Promise

   |          X---------------------------------->|    Prepare

   |          |----------------------------------X    Promise

   |---------X          |            |           |    Adopted

class Scout(Role):

def __init__(self, node, ballot_num, peers):
        super(Scout, self).__init__(node)
        self.ballot_num = ballot_num
        self.accepted_proposals = {}
        self.acceptors = set([])
        self.peers = peers
        self.quorum = len(peers) / 2 + 1
        self.retransmit_timer = None

    def start(self):
        self.logger.info("scout starting")
        self.send_prepare()

    def send_prepare(self):
        self.node.send(self.peers, Prepare(ballot_num=self.ballot_num))
        self.retransmit_timer = self.set_timer(PREPARE_RETRANSMIT, self.send_prepare)

    def update_accepted(self, accepted_proposals):
        acc = self.accepted_proposals
        for slot, (ballot_num, proposal) in accepted_proposals.iteritems():
            if slot not in acc or acc[slot][0]  ballot_num:
                acc[slot] = (ballot_num, proposal)

    def do_Promise(self, sender, ballot_num, accepted_proposals):
        if ballot_num == self.ballot_num:
            self.logger.info("got matching promise; need %d" % self.quorum)
            self.update_accepted(accepted_proposals)
            self.acceptors.add(sender)
            if len(self.acceptors) >= self.quorum:
                # strip the ballot numbers from self.accepted_proposals, now that it
                # represents a majority
                accepted_proposals = \ 
                    dict((s, p) for s, (b, p) in self.accepted_proposals.iteritems())
                # We're adopted; note that this does *not* mean that no other
                # leader is active.  # Any such conflicts will be handled by the
                # commanders.
                self.node.send([self.node.address],
                    Adopted(ballot_num=ballot_num, 
                            accepted_proposals=accepted_proposals))
                self.stop()
        else:
            # this acceptor has promised another leader a higher ballot number,
            # so we've lost
            self.node.send([self.node.address], 
                Preempted(slot=None, preempted_by=ballot_num))
            self.stop()

Leader為每個有active proposal的slot創建一個Commander角色(下圖)。像Scout一樣,Commander發送和重新發送Accept消息,并等待大多數接受者的回復Accepted或搶占消息。接受建議后,Commander將Decision消息廣播到所有節點。它用Decided或Preempted響應Leader。

Leader    Commander   Acceptor     Acceptor    Acceptor

   |          |          |            |           |   

   |          X--------->|            |           |    Accept

   |          |---------X            |           |    Accepted

   |          X---------------------->|           |    Accept

   |          |----------------------X           |    Accepted

   |          X---------------------------------->|    Accept

   |          |----------------------------------X    Accepted

   |---------X          |            |           |    Decided

class Commander(Role):

def __init__(self, node, ballot_num, slot, proposal, peers):
        super(Commander, self).__init__(node)
        self.ballot_num = ballot_num
        self.slot = slot
        self.proposal = proposal
        self.acceptors = set([])
        self.peers = peers
        self.quorum = len(peers) / 2 + 1

    def start(self):
        self.node.send(set(self.peers) - self.acceptors, Accept(
            slot=self.slot, ballot_num=self.ballot_num, proposal=self.proposal))
        self.set_timer(ACCEPT_RETRANSMIT, self.start)

    def finished(self, ballot_num, preempted):
        if preempted:
            self.node.send([self.node.address], 
                           Preempted(slot=self.slot, preempted_by=ballot_num))
        else:
            self.node.send([self.node.address], 
                           Decided(slot=self.slot))
        self.stop()

    def do_Accepted(self, sender, slot, ballot_num):
        if slot != self.slot:
            return
        if ballot_num == self.ballot_num:
            self.acceptors.add(sender)
            if len(self.acceptors)  self.quorum:
                return
            self.node.send(self.peers, Decision(
                           slot=self.slot, proposal=self.proposal))
            self.finished(ballot_num, False)
        else:
            self.finished(ballot_num, True)

有一個問題是后續會介紹的網絡模擬器甚至在節點內的消息上也引入了數據包丟失。當所有 Decision消息丟失時,該協議無法繼續進行。Replica繼續重新傳輸Propose消息,但是Leader忽略了這些消息,因為它已經對該slot提出了proposal,由于沒有Replica收到Decision所以Replica的catch過程找不到結果,解決方案是像實際網絡堆棧以西洋確保本地消息始終傳遞成功。

Bootstrap

node加入cluster時必須獲取當前的cluster狀態, Bootstrap role循環每個節點發送join消息,知道收到Welcome, Bootstrap的時序圖如下所示:

如果在每個role(replica,leader,acceptor)中實現啟動過程,并等待welcome消息,會把初始化邏輯分散到每個role,測試起來會非常麻煩,最終,我們決定添加bootstrap role,一旦啟動完成,就給node添加每個role,并且將初始狀態傳遞給他們的構造函數。

class Bootstrap(Role):

    def __init__(self, node, peers, execute_fn,
                 replica_cls=Replica, acceptor_cls=Acceptor, leader_cls=Leader,
                 commander_cls=Commander, scout_cls=Scout):
        super(Bootstrap, self).__init__(node)
        self.execute_fn = execute_fn
        self.peers = peers
        self.peers_cycle = itertools.cycle(peers)
        self.replica_cls = replica_cls
        self.acceptor_cls = acceptor_cls
        self.leader_cls = leader_cls
        self.commander_cls = commander_cls
        self.scout_cls = scout_cls

    def start(self):
        self.join()

    def join(self):
        self.node.send([next(self.peers_cycle)], Join())
        self.set_timer(JOIN_RETRANSMIT, self.join)

    def do_Welcome(self, sender, state, slot, decisions):
        self.acceptor_cls(self.node)
        self.replica_cls(self.node, execute_fn=self.execute_fn, peers=self.peers,
                         state=state, slot=slot, decisions=decisions)
        self.leader_cls(self.node, peers=self.peers, commander_cls=self.commander_cls,
                        scout_cls=self.scout_cls).start()
        self.stop()

以上就是詳解分布式系統中如何用python實現Paxos的詳細內容,更多關于python的資料請關注腳本之家其它相關文章!

您可能感興趣的文章:
  • 帶你用Python實現Saga 分布式事務的方法
  • Python搭建Spark分布式集群環境
  • python django框架中使用FastDFS分布式文件系統的安裝方法
  • Python多進程入門、分布式進程數據共享實例詳解
  • Python分布式進程中你會遇到的問題解析
  • 講解如何利用 Python完成 Saga 分布式事務

標簽:黑龍江 常德 呂梁 株洲 通遼 銅川 潛江 阿里

巨人網絡通訊聲明:本文標題《詳解分布式系統中如何用python實現Paxos》,本文關鍵詞  詳解,分布式,系統,中如,;如發現本文內容存在版權問題,煩請提供相關信息告之我們,我們將及時溝通與處理。本站內容系統采集于網絡,涉及言論、版權與本站無關。
  • 相關文章
  • 下面列出與本文章《詳解分布式系統中如何用python實現Paxos》相關的同類信息!
  • 本頁收集關于詳解分布式系統中如何用python實現Paxos的相關信息資訊供網民參考!
  • 推薦文章
    主站蜘蛛池模板: 东营程祥机械有限公司| 连云港机械有限公司| 泰安机械有限公司招聘| 邦贝液压机械有限公司| 上海 机械设备有限公司| 南阳东佳机械有限公司| 永华机械有限公司招聘| 重庆机械租赁有限公司| 温州名瑞机械有限公司| 烟台山一机械有限公司| 晋江机械制造有限公司| 三菱重工上海有限公司| 温州海翔机械有限公司| 淄博宙灿机械有限公司| 滨州 机械 有限公司| 杭州同创顶立机械有限公司| 江阴精力机械有限公司| 四川欧曼机械有限公司| 河南德润钢铁有限公司| 重庆精密机械有限公司| 湖北粮食机械有限公司| 江苏沃元精密机械有限公司| 滕州三合机械有限公司| 鑫成机械设备有限公司| 山东天力液压机械有限公司| 鑫台铭机械有限公司| 无锡锡科机械制造有限公司| 蓬莱万寿机械有限公司| 太行机械工业有限公司| 南通铁军机械有限公司| 四川腾中重工机械有限公司| 昆山台一精密机械有限公司| 无锡旭英机械有限公司| 化工有限公司起名大全| 长春泰盟机械制造有限公司 | 曼透平机械有限公司| 徐州丰展机械有限公司| 无锡市江益液压机械成套有限公司 | 晋江市机械有限公司| 旺磐精密机械有限公司| 东莞市泽源机械有限公司| 德清恒丰机械有限公司| 无锡市川中五金机械有限公司 | 华电重工机械有限公司| 天门仙粮机械有限公司| 河南大方起重机有限公司| 青州市拓新机械设备有限公司| 山东源鑫农牧机械有限公司| 湖北 机械 有限公司| 青岛给力机械有限公司| 广州市机械制造有限公司| 昆成机械(昆山)有限公司| 绵阳新晨动力机械有限公司| 济南艺高数控机械有限公司| 山东鲁丽钢铁有限公司| 长沙精密机械有限公司| 佛山市恒力泰机械有限公司| 成都液压机械有限公司| 万则盛机械有限公司| 常州金源机械设备有限公司| 上海沁艾机械设备有限公司| 山东海诺机械有限公司| 山东龙腾机械有限公司| 新乡市长城机械制造有限公司| 厦门全新彩钢机械有限公司| 青岛科尼乐重工有限公司| 鑫达机械设备有限公司| 沈阳带锯机械有限公司| 江阴市长达钢铁有限公司| 青岛三益塑料机械有限公司 | 苏州友众传动机械有限公司| 泉州市力达机械有限公司| 吉林鑫达钢铁有限公司地址| 广州凯诺机械有限公司| 诺曼艾索机械技术(北京)有限公司| 常州市 机械设备有限公司| 上海纺织机械有限公司| 济南精密机械有限公司| 佛山市钢铁有限公司| 巩义市机械有限公司| 合肥 机械有限公司| 广州泽比机械设备有限公司| 上海炬钢机械制造有限公司| 浙江新罗兰机械有限公司| 东莞市华森重工有限公司| 嘉兴市宏丰机械有限公司| 亿德隆机械有限公司| 湖州卓信机械有限公司| 中科包装机械有限公司| 宁波博大机械有限公司| 太原 机械 有限公司| 建筑工程机械租聘有限公司| 青岛一津机械有限公司| 河北宏业机械有限公司| 南通惠生重工有限公司| 江苏红旗印染机械有限公司| 杭州精工机械有限公司| 创宝包装机械有限公司| 漳州三宝钢铁有限公司| 瑞达机械设备有限公司| 海宁纺织机械有限公司| 河南黄河防爆起重机有限公司 | 中核华兴达丰工程机械有限公司 | 新风工程机械有限公司| 杭州起重吊装有限公司| 青岛武船重工有限公司| 南通机械设备有限公司| 济南耐刻机械设备有限公司| 四川兴明泰机械有限公司| 金凯达机械有限公司| 上海帆铭机械有限公司| 常州久压久机械制造有限公司 | 上海松仕机械设备有限公司 | 莱州聚峰机械有限公司| 大同机械 有限公司| 湖南信昌机械有限公司| 台州工交机械有限公司| 华劲机械制造有限公司| 廊坊 包装机械有限公司| 东莞市鸿企机械有限公司| 浙江起重机有限公司| 江苏宏博机械制造有限公司| 上海精密机械制造有限公司| 浙江温兄机械阀业有限公司| 浙江机械制造有限公司| 保定锐腾机械制造有限公司 | 张家港 机械设备有限公司| 广州伟乐机械设备有限公司| 山东博宇机械有限公司| 河北输送机械有限公司| 绵阳新晨动力机械有限公司招聘| 沧州铁狮磨浆机械有限公司| 苏州英维特精密机械有限公司| 南京 机械制造有限公司| 山东杰卓机械有限公司| 宁波创基机械有限公司| 温州宇英机械有限公司| 苏州敏喆机械有限公司| 温州轻工机械有限公司| 西安海焱机械有限公司| 广州中益机械有限公司| 湘潭丰弘机械制造有限公司| 淄博捷达机械有限公司| 大明钢铁实业有限公司| 勤堡精密机械有限公司| 嵊州市机械有限公司| 盐城三益石化机械有限公司 | 广州合成机械有限公司| 聊城新泺机械有限公司| 上海佳成服装机械有限公司| 涿州北方重工设备设计有限公司 | 广州坚诺机械设备有限公司| 湖北银轮机械有限公司| 湖南湘船重工有限公司| 郑州一本机械设备有限公司 | 三莲机械制造有限公司| 武汉萱裕机械有限公司| 青州市三联重工设备制造有限公司 | 河南发达起重机有限公司| 立信染整机械有限公司| 京山力拓机械有限公司| 浙江五一机械有限公司| 宜兴永康机械有限公司| 东莞信易电热机械有限公司| 浙江迅定钢铁有限公司| 张家港市鑫港机械有限公司| 肯拉铎机械有限公司| 天工工程机械有限公司| 杭州海陆重工有限公司| 浙江安奇迪动力机械有限公司 | 山东临沂机械有限公司| 东莞市华森重工有限公司| 安徽好运机械有限公司| 济宁福瑞得机械有限公司| 九江萍钢钢铁有限公司| 青岛双星铸造机械有限公司| 信阳众泰机械设备有限公司 | 东莞市业佳精密机械有限公司| 武汉东泰盛机械有限公司| 浙江杰豹机械有限公司| 广西 机械 有限公司| 朗维纺织机械有限公司| 定州市至信机械制造有限公司| 日照瑞荣机械有限公司| 无锡凯希迪斯机械有限公司| 青岛 数控机械有限公司| 东莞通盛机械有限公司| 浙江麒龙起重机械有限公司 | 江苏苏东机械有限公司| 西安环宇机械制造有限公司| 陀曼精密机械有限公司| 上海翔展机械有限公司| 华鑫机械制造有限公司| 大方起重机械有限公司| 南京宏伟屠宰机械制造有限公司 | 张家港和和机械有限公司| 唐山正丰钢铁有限公司| 广州东昇机械有限公司| 上海乾承机械设备有限公司| 高邮和益机械有限公司| 山东泰山机械有限公司| 大连盘起工业有限公司| 杭州速捷机械有限公司| 深圳市环球同创机械有限公司| 上海中远海运重工有限公司| 湖北大展钢铁有限公司| 山东贝特起重机有限公司| 翰林机械制造有限公司| 嘉善精密机械有限公司| 无锡万华机械有限公司| 均强机械苏州有限公司| 法麦凯尼柯机械有限公司| 五谷酿机械有限公司| 鞍山宝得钢铁有限公司| 常州昊博机械有限公司| 上海祎飞机械有限公司| 海宁美惠机械有限公司| 宏力机械设备有限公司| 佛山市南海鼎工包装机械有限公司 | 江苏优远机械有限公司| 无锡博雅德精密机械有限公司| 上海起帆电线电缆有限公司| 龙工机械制造有限公司| 山东康弘机械有限公司| 上海国豪机械制造有限公司| 江苏联顺机械有限公司| 郑州茂祥机械有限公司| 芜湖中安重工自动化装备有限公司| 深圳市宏机械设备有限公司| 深圳固尔琦包装机械有限公司| 广西清隆机械制造有限公司| 速技能机械有限公司| 南京利晨机械有限公司| 江门携成机械有限公司怎样| 莆田 机械有限公司| 江苏江成机械有限公司| 九江萍钢钢铁有限公司| 江苏维达机械有限公司| 浙江汉克机械有限公司| 德莱赛机械苏州有限公司| 菲特压片机械有限公司| 上海百勤机械有限公司| 四川腾中重工机械有限公司| 重庆信鼎精密机械有限公司| 骁马机械上海有限公司| 丹东富田精工机械有限公司| 亨内基机械上海有限公司| 临汾志强钢铁有限公司| 合肥中达机械制造有限公司| 重庆明鑫机械有限公司| 滦南华瑞钢铁有限公司| 西安亿起来贸易有限公司| 沈阳六合机械有限公司| 河南双鑫钢铁有限公司| 常州赛瑞克包装机械有限公司| 上海科峰机械有限公司| 浙江勇力机械有限公司| 凯伯精密机械有限公司| 山东长江机械有限公司| 宁波方力机械有限公司| 大连鸿升机械有限公司| 唐山龙泉机械有限公司| 上海涟恒精密机械有限公司| 机械自动化设备有限公司| 青岛塑料机械有限公司| 葛洲坝能源重工有限公司| 武汉瑞威特机械有限公司| 山东莱工机械制造有限公司| 郑州机械设备有限公司| 河北新钢钢铁有限公司| 潍坊市贝特机械有限公司| 永洋钢铁有限公司电话| 宁波钛龙机械有限公司| 浙江濠泰机械有限公司| 兴虎动力机械有限公司| 湖南省湘粮机械制造有限公司| 江苏骏马压路机械有限公司| 江苏纺织机械有限公司| 昆山 精密机械有限公司| 盐山宏润重工有限公司| 河北凯瑞重工有限公司| 东莞大同机械有限公司| 东莞恒力机械有限公司| 珠海仕高玛机械设备有限公司 | 滦南华瑞钢铁有限公司| 云南中天机械有限公司| 卡麦龙机械有限公司| 广州伟基机械有限公司| 唐山机械设备有限公司| 中信重工开诚智能装备有限公司| 临沂机械设备有限公司| 长沙威沃机械制造有限公司| 上海派协包装机械有限公司 | 南通力福通起重机械有限公司| 常州常发动力机械有限公司| 四川诚德机械有限公司| 中煤盘江重工有限公司| 深圳恒盛力包装机械有限公司| 巩义市瑞赛克机械设备有限公司| 人和弹簧机械有限公司| 河北天择重型机械有限公司| 安徽远鸿机械自动化有限公司| 杭州鸿立机械有限公司| 广州博创机械有限公司| 重庆精密机械有限公司| 重庆德运机械制造有限公司| 三友重工机械有限公司| 杭州海的机械有限公司| 杭州天杨机械有限公司| 潍坊沃富机械有限公司| 江苏盐城机械有限公司| 洛阳泽华机械设备有限公司 | 射阳县机械有限公司| 泉州机械设备有限公司| 四川腾中重工机械有限公司| 唐山龙泉机械有限公司| 江 诚机械有限公司| 徐州 机械制造有限公司| 南通庞源机械工程有限公司| 海益机械配件有限公司| 瑞安瑞泰机械有限公司| 无锡澳美机械有限公司| 山东伊莱特重工有限公司| 鞍山机械设备有限公司| 山东中悦钢铁有限公司| 海宁市腾达机械有限公司| 无锡中机械有限公司| 东莞名震机械制造有限公司| 梁发记机械有限公司| 佛山隆机械有限公司| 台州市鲨鱼食品机械有限公司| 无锡盛达机械制造有限公司| 常州市丰丰机械有限公司| 大连典石精密机械有限公司| 上海包装机械有限公司| 广州赛威机械有限公司| 五矿钢铁天津有限公司| 安徽工程机械有限公司| 江苏飞耀机械制造有限公司 | 山东曲阜 机械有限公司| 江苏双友重型机械有限公司| 山东三牛机械有限公司| 邢台 机械有限公司| 郑州昌利机械制造有限公司| 汕头机械厂有限公司| 山西汉通机械有限公司| 武汉贝瑞克机械制造有限公司| 福建联丰机械有限公司| 山东宇冠机械有限公司| 德国arku机械制造有限公司 | 海盐鼎盛机械有限公司| 廊坊 包装机械有限公司| 河南永威起重机有限公司| 石家庄工程机械有限公司| 南通中船机械制造有限公司| 浙江希望机械有限公司| 常州汤姆包装机械有限公司| 山东威海机械有限公司| 济南锐捷机械设备有限公司| 平湖机械制造有限公司| 迪威玻璃机械有限公司| 武义海拓机械有限公司| 上海盛普机械制造有限公司| 郑州机械制造有限公司| 宁波辉旺机械有限公司| 天津市仁翼钢铁有限公司| 航星洗涤机械(泰州)有限公司| 广州市力净洗涤机械有限公司| 杭州精工机械有限公司| 萨驰华辰机械 苏州 有限公司| 武汉 机械制造有限公司| 南通宝钢钢铁有限公司| 成都万欣邦达机械制造有限公司 | 昆山市众捷塑料机械有限公司| 渤海重工管道有限公司| 广州凯诺机械有限公司| 苏州爱恩机械有限公司| 广州广田包装机械有限公司| 河北东方富达机械有限公司| 广州善友机械设备有限公司| 鑫达机械设备有限公司| 西门子机械传动 天津 有限公司| 东莞市东永源机械有限公司| 立信染整机械有限公司| 郑州江科重工机械有限公司| 苏州诚亚机械有限公司| 武汉中轻机械有限公司| 济南新思路机械设备有限公司| 山东起重机厂有限公司| 重庆川凯机械有限公司| 莱州神工机械有限公司| 浙江液压机械有限公司| 上海贯博起重设备有限公司| 山东长城起重机械有限公司| 同安木工机械有限公司| 东莞市沃德精密机械有限公司| 宁波昌源机械有限公司| 南通苏诺特包装机械有限公司| 杭州速博雷尔传动机械有限公司| 淄博翔鹏机械有限公司| 鹤壁市通用机械电气有限公司| 梁山机械制造有限公司| 湖南汇杰机械设备有限公司| 江阴力达机械有限公司| 上海楷钛机械制造有限公司| 上海成套机械有限公司| 江苏优轧机械有限公司| 临海正大机械有限公司| 潍坊元鸣机械有限公司| 福海鑫钢铁有限公司| 鑫盛机械制造有限公司| 山东宇冠机械有限公司| 青岛广德机械有限公司| 亨内基机械上海有限公司| 天津安东石油机械制造有限公司| 福清市机械有限公司| 宁波星峰机械有限公司| 无锡远方机械有限公司| 常州赛瑞克包装机械有限公司| 大连科信机械有限公司| 丰润区钢铁有限公司| 浙江流遍机械润滑有限公司| 夹江水工机械有限公司| 建友机械设备有限公司| 郑州红星机械制造有限公司 | 常州艾隆精密机械有限公司| 重庆比德机械有限公司| 上海敏杰机械有限公司| 广州市荣艺食品机械有限公司 | 荣精密机械有限公司| 百超玻璃机械有限公司| 威海印刷机械有限公司| 上海环球机械有限公司| 武汉九州龙工程机械有限公司| 深圳市稻田包装机械有限公司 | 青岛越海机械有限公司| 蓬莱万寿机械有限公司| 山东战尔机械有限公司| 泰安正阳机械有限公司| 济南锐捷机械设备有限公司| 唐山凯恒钢铁有限公司| 宇进注塑机械有限公司| 河北巨牛机械有限公司| 台湾晁群机械有限公司| 潍坊瑞发机械有限公司| 诸城顺德机械有限公司| 常州艾隆精密机械有限公司| 广州工友起重设备制造有限公司| 三门峡机械有限公司| 山西海威钢铁有限公司| 上海雄风起重设备厂有限公司 | 汶上金城机械有限公司| 苏州鸿本机械制造有限公司| 圣博液压机械有限公司| 上海曼中机械有限公司| 上海喜曼机械有限公司| 江西柳工机械设备有限公司| 上海定盛机械有限公司| 同鼎机械设备有限公司| 河北德林机械有限公司| 孝感金达钢铁有限公司| 鸡西煤矿机械有限公司| 厦门厦工重工有限公司| 无锡精派机械有限公司| 德马格起重机械有限公司| 上海诚达机械有限公司| 张家港市鑫港机械有限公司| 杭州杭重机械有限公司| 诸城盛新德机械有限公司| 常州起重机械有限公司| 大连东拓工程机械制造有限公司| 苏州亿泛精密机械有限公司| 上海宁金钢铁有限公司| 华东油压机械制造有限公司 | 江苏迎阳无纺机械有限公司| 中山自动化机械有限公司| 众工机械机械有限公司| 斯特机械制造有限公司| 金沙机械制造有限公司| 莒县长运机械有限公司| 张家港市贝尔机械有限公司| 潍坊永成机械有限公司| 山西机械制造有限公司| 鞍山宝得钢铁有限公司| 山东誉亚大豆机械制造有限公司| 盐城海德机械制造有限公司| 石家庄聚力特机械有限公司 | 金坛市 机械有限公司| 东莞市三米通用机械有限公司| 延边金科食品机械有限公司| 台州市四海机械有限公司| 潞城兴宝钢铁有限公司| 江苏维达机械有限公司| 芜湖 机械制造有限公司| 江苏银华春翔机械制造有限公司| 上海金恒机械制造有限公司| 营口金辰机械有限公司| 上海舜锋机械制造有限公司| 精密机械配件有限公司| 标准缝纫机菀坪机械有限公司| 济南格特机械设备有限公司| 青县冀丰钢铁有限公司| 上海 鑫机械设备有限公司| 昆山机械 有限公司| 曲阜兴运输送机械设备有限公司| 厦门宇龙机械有限公司| 杭州合立机械有限公司| 嵊州市龙威机械制造有限公司| 宁波旭升机械有限公司| 福建机械设备有限公司| 山东瑞华工程机械有限公司| 山西美锦钢铁有限公司| 上海钊凯包装机械有限公司| 烟台微特机械有限公司| 济南 液压机械有限公司| 佛山顺德区机械有限公司| 上海山美重型矿山机械有限公司| 宁波民盛机械有限公司| 东莞木工机械有限公司| 上海江埔印刷机械有限公司| 上海二和机械有限公司| 阜阳 机械 有限公司| 西安中大机械有限公司| 宁波思进机械有限公司| 上海天和制药机械有限公司| 苏州阔泽精密机械有限公司| 东莞祥艺机械有限公司| 石油机械设备有限公司| 华东油压机械制造有限公司 | 张家港市旺巴巴机械有限公司 | 汕头市包装机械有限公司| 河南德润钢铁有限公司| 聚力特机械有限公司| 郑州锦德润机械设备有限公司| 广东森人机械有限公司| 北京液压机械有限公司| 南阳奇丰机械有限公司| 佛山市永盛达机械有限公司| 东莞市嘉鲁特注塑机械有限公司 | 重庆明鑫机械有限公司| 烟台工程机械有限公司| 贵州华泰机械设备租赁有限公司| 长沙旭众机械设备有限公司| 云南德胜钢铁有限公司| 沃洲机械制造有限公司| 江苏中热机械设备有限公司| 济宁鑫聚机械有限公司| 工程机械租赁有限公司| 青岛永正化工机械有限公司| 台正精密机械有限公司| 韶瑞重工有限公司招聘| 重庆九源机械有限公司| 常州耐强传动机械有限公司| 山东港中钢铁有限公司| 深圳市稻田包装机械有限公司 | 上海帆铭机械有限公司| 浙江科力塑料机械有限公司| 山东建筑机械有限公司| 江苏鑫林钢铁有限公司| 安徽格瑞德机械制造有限公司| 东莞市沃德精密机械有限公司| 河南点赞钢铁有限公司| 珠海市中鑫隆机械化建设工程有限公司 | 上海松精机械制造有限公司 | 杭州汽轮机械设备有限公司| 茂名重力石化机械制造有限公司| 河南矿山起重机有限公司地址| 京西重工上海有限公司| 深圳新添润彩印机械设备有限公司| 衡水机械制造有限公司| 杭州岛文机械有限公司| 扬州精辉试验机械有限公司| 宏机械铸造有限公司| 北京机械施工有限公司| 铜陵群力机械有限公司| 青岛液压机械有限公司 | 兰州华诚石化机械制造有限公司| 无锡金球机械有限公司| 重庆瀚源机械有限公司| 河南共威机械设备有限公司| 东莞 精密机械有限公司| 广东明华机械有限公司| 上海紫宏机械有限公司| 东莞市台铭数控机械有限公司| 济宁福康机械加工有限公司| 南海区机械设备有限公司| 贵州红林机械有限公司| 广东思沃精密机械有限公司| 江苏中热机械设备有限公司怎么样| 汕头机械设备有限公司| 广东正力精密机械有限公司| 佛山柯田包装机械有限公司| 浙江万宝机械有限公司| 山东鲁成起重机械有限公司| 河南重机械有限公司| 浙江青山钢铁有限公司| 上海重工机械有限公司| 常州嘉耘机械有限公司| 成都金瑞建工机械有限公司| 浙江佑天元包装机械制造有限公司 | 上海翔展机械有限公司| 洗涤机械制造有限公司| 河南卫华起重机有限公司| 江苏申特钢铁有限公司| 明辉机械设备制造有限公司| 洛阳天宇机械制造有限公司| 宜兴永康机械有限公司| 杭州群起建材有限公司| 常州小松工程机械有限公司招聘| 江苏国天锻压机械有限公司| 中山市机械设备有限公司| 苏州起重机械有限公司| 唐山盛财钢铁有限公司| 长沙凯瑞重工机械有限公司| 杭州机械制造有限公司| 四平现代钢铁有限公司| 山东胜亚机械有限公司| 江苏新瑞机械有限公司| 杭州驰丰机械有限公司| 常州达德机械有限公司| 上海美捷伦包装机械有限公司 | 天津包装机械有限公司| 江苏精明机械有限公司| 南通腾中机械有限公司| 浙江精劲机械有限公司| 河北华昌机械设备有限公司 | 洛阳重型机械有限公司| 江苏新技机械有限公司| 泰安正阳机械有限公司| 成都弘林机械有限公司| 东营海河机械有限公司| 苏州原禄机械有限公司| 常熟神马机械有限公司| 潍坊圣川机械有限公司| 诸城晶品机械有限公司| 常州国丰机械有限公司| 天津同力重工有限公司| 住友重机械有限公司| 常州动力机械有限公司| 东莞鸿祥机械有限公司| 山东山工机械有限公司| 上海立帆机械有限公司| 河北圣禹水工机械有限公司| 上海塑帝机械有限公司| 湖州惠盛机械有限公司| 苏州乐嘉机械有限公司| 江西中天机械有限公司| 沈阳德恒机械制造有限公司| 上海汉虹精密机械有限公司| 昆成机械(昆山)有限公司| 凯澄起重机械有限公司| 宝鸡中车时代工程机械有限公司 | 创达机械制造有限公司| 东芝机械上海有限公司| 临沂铸信机械有限公司| 林州市振晨重工装备制造有限公司 | 安丰钢铁有限公司电话| 河南豫弘重型机械有限公司| 赛尔透平机械有限公司| 白鸽食品机械有限公司| 泸州发展机械有限公司| 江淮重工机械有限公司| 常州汉森机械有限公司| 娄底 机械有限公司| 聊城 机械有限公司| 吉首市中诚制药机械有限公司| 浙江创伟机械有限公司| 章丘市宇龙机械有限公司| 郑州永联机械有限公司| 郑州山川重工有限公司| 重庆华世丹机械制造有限公司| 三门峡机械有限公司| 赣云食品机械有限公司| 如皋市通达机械制造有限公司 | 天津包装机械有限公司| 北京石油机械有限公司| 船舶机械制造有限公司| 昆山市升达机械制造有限公司| 上海百勤机械有限公司| 厦门众达钢铁有限公司| 杭州冠浩机械设备有限公司| 压机械制造有限公司| 宝鸡忠诚制药机械有限公司| 广州市力净洗涤机械有限公司| 常州嘉耘机械有限公司| 无锡大昌机械工业有限公司| 马鞍山钢铁有限公司| 烟台市利达木工机械有限公司| 温州市凯驰包装机械有限公司| 佛宇重工实业有限公司| 青岛德盛机械制造有限公司| 河北龙汐机械制造有限公司| 华东油压机械制造有限公司| 广东粤凯机械有限公司| 阿尔法起重机有限公司| 河北卓昊机械制造有限公司| 郑州明瑞机械设备有限公司| 邯郸纺织机械有限公司| 佛山市 重工有限公司| 四川宏华友信石油机械有限公司 | 张家港机械有限公司| 上海海韬机械有限公司| 安徽同铸工程机械有限公司| 江苏江南起重机械有限公司| 东莞市正一轴承机械有限公司 | 华威机械制造有限公司| 中核华兴达丰工程机械有限公司| 合肥中达机械制造有限公司| 潍坊宝润机械有限公司| 哈尔滨机械制造有限公司| 合肥康恒机械有限公司| 徐州压力机械有限公司| 宁波工程机械有限公司| 昆山台一精密机械有限公司| 唐山亚捷机械有限公司| 上海圣起包装机械有限公司| 山东科恳机械制造有限公司| 陕西恒德精密机械有限公司| 唐山燕山钢铁有限公司| 福建联丰机械有限公司| 郑州天龙机械有限公司| 广州精密机械有限公司| 温州市兴业机械设备有限公司 | 济南数控机械有限公司| 安徽远鸿机械自动化有限公司| 山东工程机械有限公司| 广东中龙机械有限公司| 荣嘉精密机械有限公司| 郑州华隆机械制造有限公司| 上海慧丰传动机械有限公司| 河北德龙钢铁有限公司| 江阴市机械有限公司| 常州道铖精密机械有限公司| 宁波永博机械制造有限公司| 广州新浪爱拓化工机械有限公司| 南通明德重工有限公司| 湖南威士重工机械有限公司| 曲阜润丰机械有限公司| 重庆有限公司 机械| 机械设备有限公司经营范围| 沈阳工程机械有限公司| 上海嘉倍德塑胶机械有限公司| 浙江胜代机械有限公司| 青岛安成食品机械有限公司| 珠海飞马传动机械有限公司| 泸州长江工程机械成套有限公司| 卓郎智能机械有限公司| 上海宝闽钢铁有限公司| 浙江万龙机械有限公司| 惟其信石油机械(天津)有限公司 | 长兴军毅机械有限公司| 洛阳工程机械有限公司| 浙江春江茶叶机械有限公司| 东莞市台旺机械有限公司| 武汉山推机械有限公司| 苏州柯瑞机械有限公司| 东莞市高臻机械设备有限公司 | 凹凸精密机械有限公司| 菲美得机械有限公司| 京龙工程机械有限公司| 史陶比尔精密机械电子有限公司| 三菱重工上海有限公司| 徐州彭贝机械制造有限公司| 洛阳隆中重工机械有限公司| 绍兴金昊机械制造有限公司| 济宁机械制造有限公司| 宁波拓诚机械有限公司| 上海昱钢包装机械有限公司| 中联恒通机械有限公司| 亿德隆机械有限公司| 合肥机械设备有限公司| 浙江九隆机械有限公司| 河北凯瑞重工有限公司| 江阴 起重机械有限公司| 重庆万凯机械有限公司| 东莞市力华机械设备有限公司| 合肥包装机械有限公司| 荣嘉精密机械有限公司| 北京大铭世进机械设备有限公司| 常熟机械制造有限公司| 常州新燎原机械有限公司| 济南 建筑机械有限公司| 锦州俏牌机械有限公司| 苏州琦珏机械有限公司| 瑞达机械制造有限公司| 无锡邦得机械有限公司| 东莞培锋精密机械有限公司| 重庆机械租赁有限公司| 广州东昇机械有限公司| 上海德元机械设备有限公司 | 山东博杰重型工程机械有限公司| 安徽玻璃机械有限公司| 山东通佳重工有限公司| 浙江迅定钢铁有限公司| 南阳 机械 有限公司| 承德建龙钢铁有限公司| 章丘市宇龙机械有限公司| 河南安普包装机械制造有限公司| 上海香宝机械设备有限公司| 宁波联成机械有限公司| 南通贝思特机械工程有限公司| 昆山市贝纳特机械设备有限公司 | 浙江宏涛机械有限公司| 成都杰瑞达工程机械有限公司 | 旭田包装机械有限公司| 山东三牛机械有限公司| 广州汉牛机械设备有限公司 | 特斯克机械有限公司| 章丘大成机械有限公司| 富华重工制造有限公司| 设备机械制造有限公司| 上海德机械设备有限公司| 郑州博源机械有限公司| 上海华东制药机械有限公司| 南京宏伟屠宰机械制造有限公司 | 涞源奥宇钢铁有限公司| 金华巨鑫机械有限公司| 厦门 机械有限公司| 上海机械装备有限公司| 玉溪新兴钢铁有限公司| 上海美捷伦包装机械有限公司| 机械自动化有限公司| 青岛重工机械有限公司| 新乐华宝塑料机械有限公司 | 青岛现代机械有限公司| 上海化工机械厂有限公司| 焦作巨航粮油机械有限公司| 河北宏川机械制造有限公司| 玉环博机械有限公司| 新乡高服筛分机械有限公司| 湖北机械设备有限公司| 宁波润达机械有限公司| 上海路桥机械有限公司| 国义特种钢铁有限公司| 苏州市江南石化机械有限公司| 东莞木工机械有限公司| 北京中车重工机械有限公司| 英隆机械昆山有限公司| 上海集嘉机械有限公司| 河南点赞钢铁有限公司| 东莞市业佳精密机械有限公司| 南通科邦机械有限公司| 广州新浪爱拓化工机械有限公司| 河南起重机械有限公司| 上海熊猫机械有限公司| 广州恒星冷冻机械制造有限公司| 苏州杰威尔精密机械有限公司 | 威海石岛重工有限公司| 嘉厨食品机械有限公司| 新晨动力机械有限公司| 青州康达机械有限公司| 江苏奥马机械有限公司| 桂林中天机械有限公司| 郑州升升机械有限公司| 东莞胜通机械有限公司| 淮安华辉机械设备有限公司| 江西萍乡钢铁有限公司| 东莞市恒生机械制造有限公司| 德枫丹 青岛 机械有限公司招聘| 济南龙安机械有限公司| 苏州雁达机械有限公司| 河南小松工程机械有限公司| 东莞市益彩机械有限公司| 广州普耐柯数控机械有限公司 | 汤姆包装机械有限公司| 临海正大机械有限公司| 北京城建重工有限公司| 潍坊天洁机械有限公司| 宁波丰州机械有限公司| 永兴机械设备有限公司| 山东大佳机械有限公司| 广东美特机械有限公司| 机械进出口有限公司招聘| 中兴机械制造有限公司| 广西机械设备有限公司| 食品机械(上海)有限公司| 志庆机械设备有限公司| 南京彩途机械设备有限公司| 浙江雨霖机械有限公司| 上海牛力机械有限公司| 洛阳中冶重工机械有限公司| 浙江齐鲤机械有限公司| 江苏华澄重工有限公司| 郑州机械设备有限公司| 丰润区钢铁有限公司| 宁波钢铁有限公司工作| 湖南汇一制药机械有限公司| 上海颖盛机械有限公司| 深圳巨涛机械设备有限公司| 宁波博日机械有限公司| 浙江荣亿精密机械有限公司| 中交天和机械设备制造有限公司| 上海成套机械有限公司| 河北中伟机械有限公司| 广州市善友机械设备有限公司 | 宁波市机械有限公司| 新乡市豫成振动机械有限公司 | 天津 机械制造有限公司| 山东川大机械设备有限公司| 青岛天乐机械有限公司| 科润达机械有限公司| 吉林吉钢钢铁有限公司| 马氏木工机械有限公司| 丰精密机械有限公司| 铁建重工包头有限公司| 广东锐亚机械有限公司| 中船重工重庆液压机电有限公司 | 浙江上石化机械有限公司| 昆山拓可机械有限公司| 重庆旺田机械有限公司| 定州市机械有限公司| 张家港港龙机械有限公司| 河南省黄河防爆起重机有限公司| 浙江诚泰化工机械有限公司| 上海精密机械有限公司| 山东钢铁有限公司招聘| 广州市瑞扬机械设备有限公司| 亿传玻璃机械有限公司| 广州甲宝机械有限公司| 济南森华精密机械有限公司| 浙江工程机械有限公司| 昆山日日先精密机械有限公司| 江西机械设备有限公司| 张家港机械制造有限公司| 上海沪工起重机械有限公司| 五谷酿机械有限公司| 江苏金梧机械有限公司| 浙江矿山机械有限公司| 瑞安市机械制造有限公司| 昆成机械制造有限公司| 杭州海特机械有限公司| 恩德特机械(苏州)有限公司| 河南甲庚机械设备有限公司| 柳溪机械设备有限公司| 文水海威钢铁有限公司| 上海木工机械有限公司| 物资有限公司起名大全| 单县江华机械有限公司| 阜阳 机械 有限公司| 天津市华天世纪机械有限公司| 京西重工北京有限公司| 抚顺机械设备制造有限公司| 青岛华华机械有限公司| 广东粤凯机械有限公司| 顺德机械设备有限公司| 上海众冠食品机械有限公司| 江西中天机械有限公司| 保定 机械有限公司| 如皋市通达机械制造有限公司| 临沂盖氏机械有限公司| 湖北鄂钢扬子重型机械制造有限公司| 云南中天机械有限公司| 江苏华粮机械有限公司| 柳州市超凌顺机械制造有限公司| 冷水江钢铁有限公司| 常州机械制造有限公司| 郑州长宏机械制造有限公司| 唐山东方钢铁有限公司| 郑州海特机械有限公司| 深圳起点云有限公司| 万通机械制造有限公司| 三明 机械有限公司| 人科机械陕西有限公司| 昆山精工机械有限公司| 常州高凯精密机械有限公司 | 浙江海工机械有限公司| 四川宏华友信石油机械有限公司 | 成都成邦探矿机械设备有限公司| 无锡远方机械有限公司| 浙江省机械有限公司| 淄博晟峰机械有限公司| 安特精密机械有限公司| 河北鑫晟德农业机械制造有限公司| 济宁华珠机械有限公司| 上海 食品机械有限公司| 江阴中立机械工业有限公司| 上海奉业包装机械有限公司| 湖南金牛重工机械有限公司| 上海翊特机械有限公司| 常州新燎原机械有限公司 | 上海龙工机械有限公司| 扬州诺亚机械有限公司| 西安工程机械有限公司| 东莞市五全机械有限公司| 广西美鹏机械设备有限公司| 衡阳沃力机械有限公司| 宁波金亿精密机械有限公司| 卫华起重机有限公司| 上海红重机械装备有限公司| 无锡锡洲机械有限公司| 浙江为尚机械有限公司| 江苏纺织机械有限公司| 山东河山机械有限公司| 深圳精机械有限公司| 天津国际机械阀门有限公司| 慈溪 机械 有限公司| 昆山奥德机械有限公司| 江苏华光双顺机械制造有限公司| 德昌机械制造有限公司|