2015-06-17 37 views
0

之間的對話,我面臨着這樣的局面:同步當前消息ID在Alice和Bob

Diagram

主機一個在交談通過經紀人交換消息。

當主機接收消息發送回一個傳送令牌到主機,以便它可以表明已收到他的消息的用戶。 這也可能發生另一種情況。

在任何時候一個可能處於脫機狀態和經紀人將舉行的消息,直到他們來到網上,然後拯救他們。

每個主機存儲它自己,並在數據庫表中的其他主機的消息:

ID | From | To | Msg | Type | Uid 

我用天真的表的主鍵ID將是一個不錯的選擇,以確定消息(因爲它是依賴於想通插入順序),所以我定義了一個自定義的唯一ID字段(uid)。

我的問題是:

我怎樣才能確保目前的消息ID 保持同步主機A和B之間,使得只有一個消息有ID?因此,我可以使用交付令牌標識來識別收到的消息,如果我擁有多個具有相同ID的消息,則不可能。

如果我這樣做,我們每次發送/時間天真地增加它起初它看起來不錯收到一條消息:

Host A sends message with ID 1 and increases it's current ID to 2 
Host B receives a message and increases it's current ID to 2 
Host B sends message with ID 2 and increases it's current ID to 3 
Host A receives message and increases it's current ID to 3 
... 

但它可以很容易地突破:

Host A sends message with ID 1 and increases it's current ID to 2 
Host B sends a message (before receiving the previous one) with ID 1 
clash.. two messages with ID 1 received by both hosts 

我認爲發生的每次都有一個很大的UUID(碰撞的可能性極低),但是由於每條消息都需要攜帶和存儲,所以會帶來很大的開銷。

不幸的是,任何關於經紀人的解決方案都不可行,因爲我無法觸摸經紀人的代碼。

+0

你可以添加主機ID作爲sufix到ID。 – iz25

回答

1

這是分佈式系統(課堂練習?)的典型問題。我想你試圖保持相同的ID,以便確定在Alice和Bob之間交換的所有消息中的絕對順序。如果情況並非如此,那麼john1020在評論中提供的解決方案應該足夠了。其他可能性是將ID存儲在一個可以被A和B訪問的節點中,並且分佈式鎖定機制同步訪問。這樣,即使面對衝突,你也總是定義一個訂單。但這並不總是可能的,有時效率不高。

不幸的是,沒有辦法保持絕對順序(除了擁有分佈式鎖的唯一計數器)。如果您有一個ID可以被A和B修改,您將會遇到最終一致性和碰撞風險的問題。碰撞基本上是你描述的問題。

現在,想象一下Bob和Alice同時發送一條消息,兩個集合的ID都是2.您將存儲消息的順序是什麼?其實沒關係,就像兩個人同時在電話裏說話一樣。有碰撞。

然而,有趣的是識別實際上具有序列或因果效應的消息:因此,您可以在由其他消息引起的消息之間保留一個訂單:Bob邀請Alice跳舞,Alice說yes,兩條消息與一個命令。

爲了保持這樣的順序,你可以應用一些技術,如矢量時鐘(基於Leslie Lamport的時間戳矢量算法):https://en.wikipedia.org/wiki/Vector_clock。您還可以閱讀有關AWS'DynamoDB:http://the-paper-trail.org/blog/consistency-and-availability-in-amazons-dynamo/

另外,您還可以使用Cassandra用於分佈式計數器的相同機制。這是一個很好的描述:http://www.datastax.com/wp-content/uploads/2011/07/cassandra_sf_counters.pdf