在線2k的遊戲,即使每秒合並也很吃驚。 傳統的hibernate直接庫基本上是不可能的。 我一步一步地導出了沒有鎖定的數據庫操作。 1 .同時如何沒有鎖。 用簡單的想法,把同時執行變成單線程。 Java的Disruptor就是一個很好的例子。 在java的concurrentCollection類中,原理是啟動線程運行隊列,同時運行時任務被推入隊列,線程按順序裝入此隊列。 在這種設計模式下,任何並發操作都是單線程操作,速度非常快。 當前的node.js和比較常見的ARPG服務端都是這種設計,即“大循環”體係結構。 這樣,我們原來的係統有兩個環境。 並發環境“大循環”環境並發環境是我們傳統的鎖定環境,性能正在下降。 ”大循環“環境是我們使用Disruptor打開的單線程無鎖定環境,性能高。 2 .在“大循環”環境中如何提高處理性能。 當遷移到單線程時,如果一個線程出現性能問題,整個過程必然會變慢。 因此,單線程操作絕對不能參與IO處理。 數據庫操作怎麽辦? 增加緩存。 這個想法很簡單,從內存直接讀取,必然會變快。 對於寫、更新操作,采用同樣的思路,將操作提交到一個隊列,單獨運行Thread獲取一個插件。 這確保了IO操作不會參與“大循環”。 問題再次發生了。 如果我們的遊戲隻有大周期的話,很容易解決。 因為裏麵提供了完美的同步免鎖定。 但是,實際的遊戲環境是合並和“大循環”共存,也就是上述兩種環境。 那麽,你必然會發現,不管我們怎麽設計,現金這個東西都是鎖著的。 3 .並購與“大循環”如何共存、解鎖? 我們知道,要在“大循環”中避免鎖定操作,可以使用“異步”將操作交給線程。 結合這兩個特點,對數據庫體係結構進行一點修改。 在原始緩存層中,一定存在鎖。 示例:

publicTableCache

{

privatehashmapcaches=newconcurrenthashmap (;

}這種結構是必然的,保證了在並發環境下可以正確操作緩存。 但是,“大循環”無法直接操作和修改此緩存,因此必須啟動更新緩存的線程,如下所示:

privatestaticfinalexecutorserviceexecutor=executors.newsinglethreadexecutor (;

執行程序.執行程序(newlatencyprocessor ) logs );

classlatencyprocessorimplementsrunnable

{

公共語音運行(

{

//在此可以自由修改內存數據。 采用了異步。 }

(ok,看起來很漂亮。 但是,又出了問題。 在高速訪問過程中,在緩存未被更新之前,很可能會被另一個請求重新獲取並得到舊數據。 4 .如何保證並發環境中緩存數據的唯一準確性? 我們知道,如果隻有讀取操作,沒有寫入操作,這種行為就不需要鎖定。 我使用這個技巧,在緩存的上層,添加另一個緩存,變成“一級緩存”,原來的自然變成二級緩存。 好像是CPU吧? 一級緩存隻能在“大循環”中修改,但可以在“大循環”中同時檢索,因此不需要鎖定。 如果發生數據庫更改,則可以直接操作輔助緩存,因為1 )在並發環境中更改數據庫,我們允許存在鎖定。 2 )“大循環”環境下的數據庫更改,首先將更改數據存儲在主緩存中,然後傳遞到異步修改的次緩存,修改後刪除主緩存。 這樣,無論在哪個環境中讀取數據,都首先判斷一次緩存,不判斷二次緩存。 該體係結構保證了內存數據的絕對準確性。 而且重要的是,我們要有高效的自由鎖定空間來實現我們的任何業務邏輯。 最後,還有一些提高性能的小技巧。 1 .因為我們的數據庫操作已經異步處理,所以有一段時間可能需要插入庫的數據很多。 可以通過對表、主鍵和操作類型進行排序來刪除無效操作。 例如,a )多次對同一表中同一主鍵的UPdate進行最後更新。 b )使用同一個表和同一個主鍵,隻要發生Delete,前麵的所有操作都無效。 2 .既然對操作進行排序,就一定存在按時間排序。 如何保證沒有鎖呢? 使用

privatefinalstaticatomiclong _ seq=newatomiclong (0; 可以在沒有鎖定的情況下全局保證唯一的自我增加,作為時間序列。

posted on 2015-07-1318:20 Paul wong閱讀(503 )評論)0)編輯集合所屬類別3360的性能優化