1. 程式人生 > 資料庫 >Redis高併發問題的解決方法

Redis高併發問題的解決方法

本文講述了Redis高併發問題的解決辦法。分享給大家供大家參考,具體如下:

redis為什麼會有高併發問題

redis的出身決定

redis是一種單執行緒機制的nosql資料庫,基於key-value,資料可持久化落盤。由於單執行緒所以redis本身並沒有鎖的概念,多個客戶端連線並不存在競爭關係,但是利用jedis等客戶端對redis進行併發訪問時會出現問題。發生連線超時、資料轉換錯誤、阻塞、客戶端關閉連線等問題,這些問題均是由於客戶端連線混亂造成。

同時,單執行緒的天性決定,高併發對同一個鍵的操作會排隊處理,如果併發量很大,可能造成後來的請求超時。
在遠端訪問redis的時候,因為網路等原因造成高併發訪問延遲返回的問題。

解決辦法

1.在客戶端將連線進行池化,同時對客戶端讀寫Redis操作採用內部鎖synchronized。

2.伺服器角度,利用setnx變向實現鎖機制。這個方法在實際環境中如何使用,本人並不清楚。

jedis常見錯誤分析

異常程式碼1:

複製程式碼 程式碼如下:redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool

問題分析:redis.clients.util.Pool.getResource會從JedisPool池中返回一個可用的redis連線,關於JedisPool中可用連線的配置有幾個重要的引數如下:

1.MaxActive:可用連線例項的最大數目,為負數的時候沒有限制。

2.MaxIdle:空閒連線例項的最大數目,為負值時沒有限制。

3.MaxWait:等待獲取連結的超時時間。

也就是說當連線池中沒有active/idle的連線時,會等待maxWait時間,如果等待超時還沒有可用連線,則丟擲Could not get a resource from the pool異常。所以為避免這樣的錯誤,
我們應該根據程式實際情況合理設定這三個引數的值,同時在我們獲取一個連線的程式方法中也應該合理的處理這個異常,當沒有連線可用時,等待一段時間再獲取也許是個比較好的選擇。

異常程式碼2:

複製程式碼

程式碼如下:redis.clients.jedis.exceptions.JedisConnectionException: java.net.SocketTimeoutException: Read timed out

遇到這個異常,可能會比較疑惑,redis是對記憶體的操作,速度一個在毫秒級別,在對redis操作出現秒級別的操作時會讓人感覺疑惑,但是本文開頭已經說過了,在一些特殊情況下,redis出現超時並不奇怪。jedis在初始化JedisPool時應該根據實際情況通過redis.clients.jedis.JedisPoolConfig合理設定連線池引數,通過redisPool構造方法,設定socket讀取輸入InputStream的超時時間。

`pool = new JedisPool(config,host,port,100000)`;

第四個引數是time out,單位是毫秒。可以通過合理的設定這個值來規避問題。但是這不能完全解決超時的為題。有些高併發情況下,延時返回時間甚至會達到幾十秒的極端情況。這個問題要通過程式碼層面解決redis單執行緒本身不支援鎖,在對同一個鍵進行併發操作會產生競爭的問題。

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對我們的支援。