2016-02-22 55 views
1

我打算在這方面使用MySQL,但Google Datastore看起來可能是一個可能的解決方案,我不必擔心管理服務器,這是一個很大的優勢。我需要存儲一件東西,消息。我打算有一個MySQL消息傳遞表,其中將包含來自用戶的消息給其他用戶。Google Datastore

我希望我可以將我的MySQL消息表有效地翻譯成Google數據存儲。我的要求是,使用MySQL的解決方案是:

消息只能由一個用戶發送給另一個用戶。第一次閱讀時需要更新這條消息,說明它已經被閱讀,所以如果已經閱讀,它將需要一次更新。用戶必須能夠查看其最新訂購的所有發送消息,以及最新訂購的所有消息。

我最初的設計是這樣的:

信息表:

Message_ID (BIGINT) PK auto_increment 
FromUser (INT 16) 
ToUser (INT 16) 
DateCreated (Timestamp) 
MessageText (Varchar (500)) 
HasRead (TINYINT (0=false, 1=true)) 

將要運行的查詢將包括:

SELECT * FROM messages WHERE FromUser = '10000000' ORDER BY DateCreared DESC LIMIT [starting pagination value], 10 ; //get all users sent messages - newest first, get 10 at a time 

SELECT * FROM messages WHERE ToUser= '10000000' ORDER BY DateCreared DESC LIMIT [starting pagination value], 10 ; //get all user's received messages - newest first, get 10 at a time 

UPDATE messages SET HasRead = 1 WHERE Message_ID = '123456789'; // When a message has been read update it to show it has been read. 

因此,我將有以下指標:

-Message_ID(主索引) - (FromUser,DateCreated)BTREE DESC - (ToUser,DateCreated)BTREE DESC 額外的「想要有特性,但是如果它能夠影響性能或者實現起來太複雜,他們與其他用戶的消息:

SELECT * FROM messages WHERE (FromUser = '1000000 and ToUser = '2000000') OR (FromUser = '2000000' and ToUser = '1000000') ORDER BY DateCreated DESC [starting pagination value], 10 ; // Get all the messages sent between user 1000000 and user 2000000 - newest first, fetch 10 at a time. I was thinking of creating a new column which would be be a concatenation of [smaller_userid]-[larger_userid] and search on this field instead. If this was the case I would have an additional composite index on this new column + DateCreated. SELECT * FROM messages WHERE concateduser = '1000000-2000000' ORDER BY DateCreated DESC [starting pagination value], 10 ; 

我們相信這會爲工作,但我們目前有用戶的一個活躍的社區,並估計當我們推出將頻繁使用的功能。因此,我們也希望能夠規劃未來的規模(現在還不成熟,但我們認爲這是一個非常簡單的功能,並且希望現在設計好,以節省我們未來的時間)。

所以這就是我打算用MySQL做的事情。這可以轉換成Google Datastore,它會有效嗎?

我研究了一些解決方案,但它們會相當昂貴。我的第一個想法是讓每個消息成爲一個實體。這個實體會在To,From,hash(user1 + user2)屬性上有一個索引。這將允許我獲取用戶消息,以及用戶消息的組合。問題是寫入會很昂貴,如果讀取的消息會更新,則更新會很昂貴。查詢也很昂貴,如果我最初加載10條消息,它將花費1 + 10個讀取單位。我嘗試了另一種在一個實體中存儲N個消息的解決方案。對於每個用戶,我需要存儲他們當前處於哪個實體的費用,因爲對於每條消息,我需要兩次寫入相同的數據(每個用戶一次),兩組都需要更新,另外還有額外的讀取以獲取用戶在插入或閱讀消息時所處的當前實體。我正在尋找這個簡單要求的更好的解決方案。

回答

3

這一切都取決於你的昂貴的定義。

你的一個消息一個實體設計當然看起來最明智。

隨着4次寫入(實體+索引)發送一百萬郵件將花費:

(0.6/100000) * 4 * 1000000 = 24美分

另一個24美分標記爲已讀

如果我們假設每封郵件會導致到至少一個讀取查詢(對於一組10個)(0.6/100000) * 11 * 1000000 = 66美分

如果我們假設每條消息都是tak ES約150個字符,然後將它們存儲,每月將花費(1000000 * 150/1024000000) * 0.18 =約2.6一個月美分,不過這是添加劑,那麼一年後,你會得到回報31.2美分,等

所以我們會發現什麼呢?閱讀是相對昂貴的,或者說查詢是昂貴的。你會做很多。您還沒有考慮到可能的不同場景(例如,如果您想向用戶展示他們有多少條未讀消息,那該怎麼辦?)。

所以你會想積極地memcache這些查詢,但你會發現約eventual consistency。簡而言之,使用數據存儲時,查詢不會(總是)包含您事先寫入的所有結果(最終)。這使緩存變得困難,因爲很難知道您的查詢何時會更新。

您很可能最終會使用Ancestors and Entity Groups來解決此問題,本質上,您的消息將圍繞根實體(代表用戶)分組。由於這提供了強大的一致性和原子性,因此您會發現這提供了保留某些信息的自然點。這個與用戶相關的實體可以存儲諸如未讀消息的數量,甚至所有未讀消息的ID的列表,最後10條消息等。

然後這可以積極地memcached(在),消息本身也可以。這意味着,在理想的情況下,您只能編寫消息和用戶實體,並且您可以在沒有單個查詢甚至讀取的情況下單擊它時顯示未讀消息數,前10條消息和消息本身。

祖先查詢帶有成本,而不是以美分爲單位,但是具有寫入能力。這將被限制爲(最壞的情況下)一組中的所有實體每秒寫入一次(所以一個用戶)。這應該不是問題(除非您希望用戶每隔幾秒鐘才能收到更多消息),但是您仍然必須考慮到寫入操作有時會失敗並需要重新嘗試。

選擇是否使用祖先是一個重要的決定,這並非不可能,但以後很難遷移到此模型。但我個人會堅持進行其他積極的性能優化,直到您看到實際成本。基本上,無論您每月還是每秒執行一百萬條消息,性能在此模型中都會保持不變,您的資金可能會更好地用於其他方面,以增加用戶的收入,而不是試圖從Datastore中擠出最後幾分錢。