激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 使用JAVA實現高并發無鎖數據庫操作步驟分享

使用JAVA實現高并發無鎖數據庫操作步驟分享

2019-10-21 12:05java教程網 Java教程

一個在線2k的游戲,每秒鐘并發都嚇死人。傳統的hibernate直接插庫基本上是不可行的。我就一步步推導出一個無鎖的數據庫操作,詳情看下文

1. 并發中如何無鎖。
一個很簡單的思路,把并發轉化成為單線程。Java的Disruptor就是一個很好的例子。如果用java的concurrentCollection類去做,原理就是啟動一個線程,跑一個Queue,并發的時候,任務壓入Queue,線程輪訓讀取這個Queue,然后一個個順序執行。 
在這個設計模式下,任何并發都會變成了單線程操作,而且速度非常快。現在的node.js, 或者比較普通的ARPG服務端都是這個設計,“大循環”架構。
這樣,我們原來的系統就有了2個環境:并發環境 + ”大循環“環境
并發環境就是我們傳統的有鎖環境,性能低下。
"大循環"環境是我們使用Disruptor開辟出來的單線程無鎖環境,性能強大。

2. ”大循環“環境 中如何提升處理性能。
一旦并發轉成單線程,那么其中一個線程一旦出現性能問題,必然整個處理都會放慢。所以在單線程中的任何操作絕對不能涉及到IO處理。那數據庫操作怎么辦?
增加緩存。這個思路很簡單,直接從內存讀取,必然會快。至于寫、更新操作,采用類似的思路,把操作提交給一個Queue,然后單獨跑一個Thread去一個個獲取插庫。這樣保證了“大循環”中不涉及到IO操作。

問題再次出現:
如果我們的游戲只有個大循環還容易解決,因為里面提供了完美的同步無鎖。
但是實際上的游戲環境是并發和“大循環”并存的,即上文的2種環境。那么無論我們怎么設計,必然會發現在緩存這塊上要出現鎖。

3. 并發與“大循環”如何共處,消除鎖?
我們知道如果在“大循環”中要避免鎖操作,那么就用“異步”,把操作交給線程處理。結合這2個特點,我稍微改下數據庫架構。
原本的緩存層,必然會存在著鎖,例如:

 

復制代碼代碼如下:

public TableCache
{
  private HashMap<String, Object> caches = new ConcurrentHashMap<String, Object>();
}

 

這個結構是必然的了,保證了在并發的環境下能夠準確的操作緩存。但是”大循環“卻不能直接操作這個緩存進行修改,所以必須啟動一個線程去更新緩存,例如:

 

復制代碼代碼如下:


private static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();
EXECUTOR.execute(new LatencyProcessor(logs));

 

class LatencyProcessor implements Runnable
{
  public void run()
  { 
    // 這里可以任意的去修改內存數據。采用了異步。
  }
}

 

OK,看起來很漂亮。但是又有個問題出現了。在高速存取的過程中,非常有可能緩存還沒有被更新,就被其他請求再次獲取,得到了舊的數據。

4. 如何保證并發環境下緩存數據的唯一正確?
我們知道,如果只有讀操作,沒有寫操作,那么這個行為是不需要加鎖的。
我使用這個技巧,在緩存的上層,再加一層緩存,成為”一級緩存“,原來的就自然成為”二級緩存“。有點像CPU了對不?
一級緩存只能被”大循環“修改,但是可以被并發、”大循環“同時獲取,所以是不需要鎖的。
當發生數據庫變動,分2種情況:
1)并發環境下的數據庫變動,我們是允許有鎖的存在,所以直接操作二級緩存,沒有問題。
2)”大循環“環境下數據庫變動,首先我們把變動數據存儲在一級緩存,然后交給異步修正二級緩存,修正后刪除一級緩存。
這樣,無論在哪個環境下讀取數據,首先判斷一級緩存,沒有再判斷二級緩存。
這個架構就保證了內存數據的絕對準確。
而且重要的是:我們有了一個高效的無鎖空間,去實現我們任意的業務邏輯。

最后,還有一些小技巧提升性能。
1. 既然我們的數據庫操作已經被異步處理,那么某個時間,需要插庫的數據可能很多,通過對表、主鍵、操作類型的排序,我們可以刪除一些無效操作。例如:
a)同一個表同一個主鍵的多次UPdate,取最后一次。
b)同一個表同一個主鍵,只要出現Delete,前面所有操作無效。
2. 既然我們要對操作排序,必然會存在一個根據時間排序,如何保證無鎖呢?使用
private final static AtomicLong _seq = new AtomicLong(0);
即可保證無鎖又全局唯一自增,作為時間序列。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: av在线免费播放网站 | 一本色道久久综合亚洲精品图片 | 一级成人免费 | 国产电影精品久久 | 黑人一级片视频 | 美女福利视频国产 | 色婷婷综合久久久中字幕精品久久 | 依依成人精品视频 | 久久亚洲国产午夜精品理论片 | 国产超碰人人爽人人做人人爱 | 日韩精品一区二区久久 | 成年免费观看视频 | 中文字幕精品亚洲 | 成人免费久久 | 亚洲生活片 | 九九热国产在线 | 91久久在线观看 | 热久久91| 精品亚洲免费 | 精品一区二区三区免费毛片 | 日本中文字幕久久 | 精品中文字幕视频 | 中文字幕极速在线观看 | 国产激情精品一区二区三区 | h视频在线观看免费 | 欧美精品一区二区三区在线 | 中文字幕在线不卡视频 | 精品久久久久久久久久 | 国产一级不卡毛片 | av在线免费观看播放 | 精品一区二区三区在线播放 | 久久国产在线观看 | 久久精片 | 国产自91精品一区二区 | 国产精品视频一区二区噜噜 | 天堂精品在线 | 成人羞羞在线观看网站 | 国产伦乱视频 | 国产午夜精品一区二区三区不卡 | 久久精品视频69 | 久久久精品视频免费看 |