天天看點

Redis連接配接失敗問題排查和解決

作者:網際網路進階架構師

當你的應用服務在連接配接Redis時出現了拒絕連接配接的場景,首先你可以根據調整Redis執行個體參數maxclients的配置。maxclients代表着最大同時連接配接的用戶端個數,Proxy叢集執行個體不支援該參數,取值範圍1,000~50,000,預設值:10,000,可以調整的再大一些。

Redis連接配接失敗問題排查和解決

用戶端拒接連接配接問題

如果你使用的是叢集模式,而使用用戶端連接配接進行連接配接Cluster叢集時,連接配接失敗出現Read timed out或Could not get a resource from the pool。

分析排查方向

  • 排查是否使用了keys指令,keys指令會消耗大量資源,造成Redis阻塞。建議使用scan指令替代,且避免頻繁執行。
  • 當Redis資料持久化即AOF時,會觸發偶現的磁盤性能問題,導緻連接配接異常,可更換Redis所在磁盤更新為ssd盤,磁盤性能更高,或若不需要持久化可關閉AOF。

unexpected end of stream錯誤,導緻業務異常。

分析排查方向

Jedis連接配接池調優,建議參考Jedis參數配置建議進行配置連接配接池參數。

Jedis連接配接池優勢

Lettuce用戶端及Jedis用戶端比較如下:

  • Lettuce: Lettuce用戶端沒有連接配接保活探測,錯誤連接配接存在連接配接池中會造成請求逾時報錯。 Lettuce用戶端未實作testOnBorrow等連接配接池檢測方法,無法在使用連接配接之前進行連接配接校驗。
  • Jedis: Jedis用戶端實作了testOnBorrow、testWhileIdle、testOnReturn等連接配接池校驗配置。 開啟testOnBorrow在每次借用連接配接前都會進行連接配接校驗,可靠性最高,但是會影響性能(每次Redis請求前會進行探測)。 testWhileIdle可以在連接配接空閑時進行連接配接檢測,合理配置門檻值可以及時剔除連接配接池中的異常連接配接,防止使用異常連接配接造成業務報錯。 在空閑連接配接檢測之前,連接配接出現問題,可能會造成使用該連接配接的業務報錯,此處可以通過參數控制檢測間隔(timeBetweenEvictionRunsMillis)。
是以,Jedis用戶端在面對連接配接異常,網絡抖動等場景下的異常處理和檢測能力明顯強于Lettuce,可靠性更強。

maxTotal(最大連接配接)

根據Web容器的Http線程數來進行配置,估算單個Http請求中可能會并行進行的Redis調用次數,例如:Tomcat中的Connector内的maxConnections配置為150,每個Http請求可能會并行執行2個Redis請求,在此之上進行部分預留,則建議配置至少為:150 x 2 + 100= 400。

限制條件

單個Redis執行個體的最大連接配接數。maxTotal和用戶端節點數(CCE容器或業務VM數量)數值的乘積要小于單個Redis執行個體的最大連接配接數。

例如:Redis主備執行個體配置maxClients為10000,單個用戶端maxTotal配置為500,則最大用戶端節點數量為20個。

maxIdle(最大空閑連接配接)

建議配置為maxTotal一緻。

minIdle(最小空閑連接配接)

一般來說建議配置為maxTotal的幾分之一。

例如,此處正常配置建議為:100。對于性能敏感的場景,防止經常連接配接數量抖動造成影響,也可以配置為與maxIdle一緻,例如:400。

maxWaitMillis(最大擷取連接配接等待時間)

機關:毫秒

擷取連接配接時最大的連接配接池等待時間,根據單次業務最長容忍的失敗時間減去執行指令的逾時時間得到建議值。

例如:Http最大容忍逾時時間為15s,Redis請求的timeout設定為10s,則此處可以配置為5s。

timeout(指令執行逾時時間)

機關:毫秒

單次執行Redis指令最大可容忍的逾時時間,根據業務程式的邏輯進行選擇,一般來說處于對網絡容錯等考慮至少建議配置為210ms以上。特殊的探測邏輯或者環境異常檢測等,可以适當調整達到秒級。

minEvictableIdleTimeMillis(空閑連接配接逐出時間)

大于該值的空閑連接配接一直未被使用則會被釋放,機關:毫秒

如果希望系統不會經常對連接配接進行斷鍊重建,此處可以配置一個較大值(xx分鐘),或者此處配置為-1,并且搭配空閑連接配接檢測進行定期檢測。

timeBetweenEvictionRunsMillis(空閑連接配接探測時間間隔)

機關:毫秒

根據系統的空閑連接配接數量進行估算,例如,系統的空閑連接配接探測時間配置為30s,則代表每隔30s會對連接配接進行探測,如果30s内發生異常的連接配接,經過探測後會進行連接配接排除。

根據連接配接數的多少進行配置,如果連接配接數太大,配置時間太短,會造成請求資源浪費。對于幾百級别的連接配接,正常來說建議配置為30s,可以根據系統需要進行動态調整。

testOnBorrow(進行擷取連接配接檢測)

向資源池借用連接配接時是否做連接配接有效性檢測(ping),檢測到的無效連接配接将會被移除。

對于業務連接配接極端敏感的,并且性能可以接受的情況下,可以配置為True,一般來說建議配置為False,啟用連接配接空閑檢測。

testWhileIdle

是否在空閑資源監測時通過ping指令監測連接配接有效性,無效連接配接将被銷毀。一般設定為True。

testOnReturn

向資源池歸還連接配接時是否做連接配接有效性檢測(ping),檢測到無效連接配接将會被移除。一般設定為False。

maxAttempts

在JedisCluster模式下,您可以配置maxAttempts參數來定義失敗時的重試次數。建議配置3-5之間,預設配置為5。

根據業務接口最大逾時時間和單次請求的timeout綜合配置,最大配置不建議超過10,否則會造成單次請求處理時間過長,接口請求阻塞。

排查是否大key較多,建議根據優化大key排查優化。

  • string類型控制在10KB以内,hash、list、set、zset元素盡量不超過5000。
  • Key的命名字首為業務縮寫,禁止包含特殊字元(比如空格、換行、單雙引号以及其他轉義字元)。
  • Redis事務功能較弱,不建議過多使用。
  • 短連接配接性能差,推薦使用帶有連接配接池的用戶端。
  • 如果隻是用于資料緩存,容忍資料丢失,建議關閉持久化。

Key/熱Key的優化方法

什麼是大Key,大Key可以分為兩種情況?

  • Key的Value較大,例如一個String類型的Key大小達到10MB,或者一個集合類型(Hash,List,Set等)的元素總大小達到了100MB。一般我們定義單個String類型的Key大小達到10KB,或者集合類型的Key總大小達到50MB,則定義其為大Key。
  • Key的元素較多,例如一個Hash類型的Key,其元素數量達到了10000。一般我們定義集合類型的Key中元素超過5000個,則認為其為大Key。

熱Key

通常以一個Key被操作的頻率和占用的資源來判定其是否為熱Key,例如:

  • 某個叢集執行個體一個分片每秒處理10000次請求,其中有3000次都是操作同一個Key。
  • 某個叢集執行個體一個分片的總帶寬使用(入帶寬+出帶寬)為100Mbits/s,其中80Mbits是由于對某個Hash類型的Key執行HGETALL所占用。

進行大Key拆分,分為以下幾種場景:

  1. 該對象為String類型的大Key:可以嘗試将對象分拆成幾個Key-Value, 使用MGET或者多個GET組成的pipeline擷取值,分拆單次操作的壓力,對于叢集來說可以将操作壓力平攤到多個分片上,降低對單個分片的影響。
  2. 該對象為集合類型的大Key,并且需要整存整取:在設計上嚴格禁止這種場景的出現,因為無法拆分。有效的方法是将該大Key從Redis去除,單獨放到其餘存儲媒體上。
  3. 該對象為集合類型的大Key,每次隻需操作部分元素:将集合類型中的元素分拆。以Hash類型為例,可以在用戶端定義一個分拆Key的數量N,每次對HGET和HSET操作的field計算哈希值并取模N,确定該field落在哪個Key上,實作上類似于Redis Cluster的計算slot的算法。
  4. 無法拆分的大Key建議使用此方法,将不适用Redis能力的資料存至其它存儲媒體,如SFS或者其餘NoSQL資料庫,并在Redis中删除該大Key。

注意:

  • 禁止使用DEL直接删除大Key,可能會造成Redis阻塞,甚至主備倒換。高版本4.0以上,可以使用unlink。
  • 合理設定過期時間并對過期資料定期清理。
  • 合理設定過期時間,避免曆史資料在Redis中大量堆積。由于Redis的惰性删除政策,過期資料可能并不能及時清理,如果發現Redis過期Key清理較慢,可以手動使用scan進行掃描删除。

熱Key,如何處理控制

  • 使用讀寫分離。

如果熱Key主要是讀流量較大,則可以實作讀寫分離架構,降低對主節點的影響。還可以增加多個副本以滿足讀需求,但是備機較多也有相應的影響,即所有的備節點都直接和主節點保持同步,這樣能保證備節點之間互相獨立,且複制延遲較小。缺點是在備節點數量較多的情況下,主節點的CPU和網絡負載會較高。

  • 使用用戶端緩存/本地緩存。

該方案需要提前了解業務的熱點Key有哪些,設計用戶端/本地和遠端Redis的兩級緩存架構,熱點資料優先從本地緩存擷取,寫入時同時更新,這樣能夠分擔熱點資料的大部分讀壓力。缺點是需要修改用戶端架構和代碼,改造成本較高。

  • 設計熔斷/降級機制。

熱Key極易造成緩存擊穿,高峰期請求都直接透傳到後端資料庫上,進而導緻業務雪崩。是以熱Key的優化一定需要設計系統的熔斷/降級機制,在發生擊穿的場景下進行限流和服務降級,保護系統的可用性。

作者:洛神灬殇

連結:https://juejin.cn/post/7199643079284179003

來源:稀土掘金

繼續閱讀