2010-11-09 41 views
1

還有一些關於併發的SO問題,但它們不能很好地解決我的情況。網頁遊戲併發控制

所以我們可以說,我有一個遊戲,用戶彼此,戰鬥和諸如此類的東西互動。在任何時候,玩家都可能參與與其他玩家的多次交互,他們都可以看到事件的發生。當這些玩家中的任何一個碰到該網站時,它需要更新涉及的任何數據並將其顯示給用戶。

例的情況:玩家A與玩家B的戰鬥和事件,在這場鬥爭中,每隔幾分鐘發生。與此同時,玩家A也與玩家C進行互動。通過愚蠢的運氣,這兩次互動的事件恰巧發生在同一秒。

當第二次到達時,再次運氣不佳,玩家B和玩家C同時擊中該網站,以便檢查他們與玩家A的戰鬥狀態。戰鬥需要更新關於玩家A的信息。如果我沒有正確編碼,A的數據可能會混亂。

我有兩種遊戲有這種情況,每種都有不同的解決方案和不同的問題。其中一個用戶使用鎖,因此當用戶點擊該站點時,他們獲取數據庫行的鎖,讀取他們成功獲取的鎖的數據,然後寫入更改並釋放鎖。但有時候,由於原因仍然未知,這會失敗,並且鎖定永久停滯,用戶抱怨,我們必須手動修復它。我的其他遊戲使用守護進程來執行這些事務,這使得問題(近乎)變得無關緊要,因爲只有一個進程正在進行這些更改。但玩家仍然可以同時做其他事情,並可能導致同樣的問題。

我已經讀了一些關於不同的解決方案,如樂觀或基於時間戳的控件。我想問一下:

  1. 哪一個最常用於像我這樣的情況,哪個最容易實現?

  2. 我的下一個項目使用的Kohana(PHP)和它的ORM,所以我的數據庫默認情況下寫的形式會是「只是簡單地覆蓋所有這些領域。」我是否需要爲此編寫自己的更新查詢,還是可以獲得與ORM兼容的解決方案?

  3. 如何處理涉及多個表的交易?戰鬥的結果必須改變戰鬥表和玩家信息表,可能還有更多的事情。哪些解決方案更容易在這裏使用?我的所有表都需要事務時間戳列嗎?

  4. 很多這些解決方案的說,當有衝突,無論是重試或忽略。這對我意味着什麼? 「重試」意味着重新啓動我的整個腳本,這將導致用戶額外的加載時間?我不認爲忽略是一個有效的選擇,因爲事件必須在某個時刻執行。在我發現的其他問題中,向用戶呈現衝突錯誤通常是一種有效的選擇 - 對我而言,事實並非如此。

  5. 什麼是併發控制對性能的影響 - 它甚至值得嗎?

回答

0

我認爲你正在尋找的東西已經包含在你的問題中:交易。 如果您使用MySQL,您將需要使用innoDb引擎設置您的表以便能夠使用事務。一些文檔:

不要嘗試時,你可以推倒重來。

+0

但是當我讀完要修改的數據後,我在進行計算的時候無法修改數據?在提交我的事務之前,我必須手動驗證數據沒有被更改,但驗證和提交本身不是原子的。或者,如果我的查詢是「更新WHERE所有數據是我期望的」,並且如果我得到0行受影響,我知道我需要重試? – Tesserex 2010-11-09 16:15:22

+0

Ahh - 選擇FOR UPDATE。所以對於2.我必須修改我的ORM中的一些東西。對於問題4 - 我不需要重試,因爲它會一直讀取最新的數據? – Tesserex 2010-11-09 16:26:40

+0

問題是,由於php的單一請求操作模式,用戶可能會看到某些東西(第一個請求),並在另一個用戶之後執行其他操作。 但是他們通常知道它可能會發生(這就是爲什麼在某些遊戲中,您有大F5用戶幾乎可以實時檢查發生了什麼:p),但只要您在任何計算之前開始事務並提交或回滾到最後,如果您在執行操作之前檢查條件來做某件事情,那麼您應該沒有問題。 – Arkh 2010-11-09 16:46:16