redis學習筆記二

http://redisbook.readthedocs.io/en/latest/java

redis爲何會有高併發問題redis

  • redis的出身決定

redis是一種單線程機制的nosql數據庫,基於key-value,數據可持久化落盤。因爲單線程因此redis自己並無鎖的概念,多 個客戶端鏈接並不存在競爭關係,可是利用jedis等客戶端對redis進行併發訪問時會出現問題。發生鏈接超時、數據轉換錯誤、阻塞、客戶端關閉鏈接等 問題,這些問題均是因爲客戶端鏈接混亂形成。sql


同時,單線程的天性決定,高併發對同一個鍵的操做會排隊處理,若是併發量很大,可能形成後來的請求超時。數據庫

在遠程訪問redis的時候,由於網絡等緣由形成高併發訪問延遲返回的問題。服務器

解決辦法網絡

  • 在客戶端將鏈接進行池化,同時對客戶端讀寫Redis操做採用內部鎖synchronized。
  • 服務器角度,利用setnx變向實現鎖機制。這個方法在實際環境中如何使用,本人並不清楚。

jedis常見錯誤分析併發

異常代碼1:nosql

redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the poolsocket

問題分析:redis.clients.util.Pool.getResource會從JedisPool池中返回一個可用的redis鏈接,關於JedisPool中可用鏈接的配置有幾個重要的參數以下:高併發

MaxActive:可用鏈接實例的最大數目,爲負數的時候沒有限制。

MaxIdle:空閒鏈接實例的最大數目,爲負值時沒有限制。

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單線程自己不支持鎖,在對同一個鍵進行併發操做會產生競爭的問題。

相關文章
相關標籤/搜索