導航:首頁 > 源碼編譯 > java高並發秒殺源碼

java高並發秒殺源碼

發布時間:2024-10-27 20:11:16

㈠ 高並發情況下怎樣盡量實現無鎖編程

一個在線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);

即可保證無鎖又全局唯一自增,作為時間序列。

㈡ java程序領取優惠卷,高並發下怎麼避免領取量超過預發量

基本思路是:鎖+冪等性

具體實現:

使用redis的decr (對key對應的數字做減1操作。如果key不存在,那麼在操作之前,這個key對應的值會被置為0。如果key有一個錯誤類型的value或者是一個不能表示成數字的字元串,就返回錯誤。這個操作最大支持在64位有符號的整型數字。)可以實現原子性的遞增遞減操作控制優惠碼不超送,然後給每個用戶維護一個userid+優惠碼活動的key保證冪等性,只要redis存在這種key,那就代表已經領取了,具體的優惠碼分發可以非同步執行。為了避免競爭(同一個用戶,多個設備同時領取),參考:網頁鏈接

閱讀全文

與java高並發秒殺源碼相關的資料

熱點內容
androidauto語音 瀏覽:51
雲繳費app兌換碼在哪裡 瀏覽:623
聖地安列斯安卓版存檔怎麼用 瀏覽:201
在哪裡可以找到舊版本的app 瀏覽:373
一個客戶端如何連接多個伺服器 瀏覽:883
簡訊加密的作用 瀏覽:108
微型高壓空氣壓縮機 瀏覽:520
微信app如何翻譯視頻 瀏覽:860
考試前聽什麼歌解壓 瀏覽:474
哪個app充值可以用銀聯二維碼 瀏覽:566
女程序員和孩子玩 瀏覽:839
程序員蘇州武漢 瀏覽:754
大腳插件如何切換安卓 瀏覽:943
python課設製作年歷 瀏覽:405
明文在pdf 瀏覽:751
鄭永令pdf 瀏覽:122
cad命令行坐標輸入 瀏覽:781
編譯原理csdn博客 瀏覽:194
想在深圳買房關注哪個app 瀏覽:913
國際體驗服為什麼伺服器載入失敗 瀏覽:690