欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

redis大key和大value的危害及解決

 更新時間:2024年03月21日 10:31:15   作者:逆流°只是風景-bjhxcc  
本文主要介紹了redis大key和大value的危害及解決

一、前序

還記得上次和同事一起去面試候選人時,同事提了一個問題:Redis的大key有什么危害?當時候選人主要作答的角度是一個key的value較大時的情況,比如:

  • 內存不均:單value較大時,可能會導致節(jié)點之間的內存使用不均勻,間接地影響key的部分和負載不均勻;
  • 阻塞請求:redis為單線程,單value較大讀寫需要較長的處理時間,會阻塞后續(xù)的請求處理;
  • 阻塞網(wǎng)絡:單value較大時會占用服務器網(wǎng)卡較多帶寬,可能會影響該服務器上的其他Redis實例或者應用。

雖說答的是挺好的,但是我又隨之產(chǎn)生了另一個疑惑,如果redis的key較長時,會產(chǎn)生什么樣的影響呢?查了很多文章,說的都不是特別清楚。所以我決心探究一下這個問題。

我們需要知道Redis是如何存儲key和value的:

根結構為RedisServer,其中包含RedisDB(數(shù)據(jù)庫)。而RedisDB實際上是使用Dict(字典)結構對Redis中的kv進行存儲的。這里的key即字符串,value可以是string/hash/list/set/zset這五種對象之一。

在這里插入圖片描述

Dict字典結構中,存儲數(shù)據(jù)的主題為DictHt,即哈希表。而哈希表本質上是一個DictEntry(哈希表節(jié)點)的數(shù)組,并且使用鏈表法解決哈希沖突問題(關于哈希沖突的解決方法可以參考大佬的文章 解決哈希沖突的常用方法分析)。

所以在這里實際存儲時,key和value都是存儲在DictEntry中的。所以基本上來說,大key和大value帶來的內存不均和網(wǎng)絡IO壓力都是一致的,只是key相較于value還多一個做hashcode和比較的過程(鏈表中進行遍歷比較key),會有更多的內存相關開銷。

二、什么是Redis大key問題

Redis大key問題指的是某個key對應的value值所占的內存空間比較大,導致Redis的性能下降、內存不足、數(shù)據(jù)不均衡以及主從同步延遲等問題。

到底多大的數(shù)據(jù)量才算是大key?

沒有固定的判別標準,通常認為字符串類型的key對應的value值占用空間大于1M,或者集合類型的k元素數(shù)量超過1萬個,就算是大key。

Redis大key問題的定義及評判準則并非一成不變,而應根據(jù)Redis的實際運用以及業(yè)務需求來綜合評估。例如,在高并發(fā)且低延遲的場景中,僅10kb可能就已構成大key;然而在低并發(fā)、高容量的環(huán)境下,大key的界限可能在100kb。因此,在設計與運用Redis時,要依據(jù)業(yè)務需求與性能指標來確立合理的大key閾值。

三、大key帶來的影響

  • 內存占用過高。大Key占用過多的內存空間,可能導致可用內存不足,從而觸發(fā)內存淘汰策略。在極端情況下,可能導致內存耗盡,Redis實例崩潰,影響系統(tǒng)的穩(wěn)定性。
  • 性能下降。大Key會占用大量內存空間,導致內存碎片增加,進而影響Redis的性能。對于大Key的操作,如讀取、寫入、刪除等,都會消耗更多的CPU時間和內存資源,進一步降低系統(tǒng)性能。
  • 阻塞其他操作。某些對大Key的操作可能會導致Redis實例阻塞。例如,使用DEL命令刪除一個大Key時,可能會導致Redis實例在一段時間內無法響應其他客戶端請求,從而影響系統(tǒng)的響應時間和吞吐量。
  • 網(wǎng)絡擁塞。每次獲取大key產(chǎn)生的網(wǎng)絡流量較大,可能造成機器或局域網(wǎng)的帶寬被打滿,同時波及其他服務。例如:一個大key占用空間是1MB,每秒訪問1000次,就有1000MB的流量。
  • 主從同步延遲。當Redis實例配置了主從同步時,大Key可能導致主從同步延遲。由于大Key占用較多內存,同步過程中需要傳輸大量數(shù)據(jù),這會導致主從之間的網(wǎng)絡傳輸延遲增加,進而影響數(shù)據(jù)一致性。
  • 數(shù)據(jù)傾斜。在Redis集群模式中,某個數(shù)據(jù)分片的內存使用率遠超其他數(shù)據(jù)分片,無法使數(shù)據(jù)分片的內存資源達到均衡。另外也可能造成Redis內存達到maxmemory參數(shù)定義的上限導致重要的key被逐出,甚至引發(fā)內存溢出。

四、大key產(chǎn)生的原因

  • 業(yè)務設計不合理。這是最常見的原因,不應該把大量數(shù)據(jù)存儲在一個key中,而應該分散到多個key。例如:把全國數(shù)據(jù)按照省行政區(qū)拆分成34個key,或者按照城市拆分成300個key,可以進一步降低產(chǎn)生大key的概率。
  • 沒有預見value的動態(tài)增長問題。如果一直添加value數(shù)據(jù),沒有刪除機制、過期機制或者限制數(shù)量,遲早出現(xiàn)大key。例如:微博明星的粉絲列表、熱門評論等。
  • 過期時間設置不當。如果沒有給某個key設置過期時間,或者過期時間設置較長。隨著時間推移,value數(shù)量快速累積,最終形成大key。
  • 程序bug。某些異常情況導致某些key的生命周期超出預期,或者value數(shù)量異常增長 ,也會產(chǎn)生大key。

五、怎樣排查大key

SCAN命令

通過使用Redis的SCAN命令,我們可以逐步遍歷數(shù)據(jù)庫中的所有Key。結合其他命令(如STRLEN、LLEN、SCARD、HLEN等),我們可以識別出大Key。SCAN命令的優(yōu)勢在于它可以在不阻塞Redis實例的情況下進行遍歷。

bigkeys參數(shù)

使用redis-cli命令客戶端,連接Redis服務的時候,加上 —bigkeys 參數(shù),可以掃描每種數(shù)據(jù)類型數(shù)量最大的key。

redis-cli -h 127.0.0.1 -p 6379 —bigkeys

Redis RDB Tools工具

使用開源工具Redis RDB Tools,分析RDB文件,掃描出Redis大key。
例如:輸出占用內存大于1kb,排名前3的keys。

rdb —commond memory —bytes 1024 —largest 3 dump.rbd

六、怎么解決大key

拆分成多個小key。這是最容易想到的辦法,降低單key的大小,讀取可以用mget批量讀取。

數(shù)據(jù)壓縮。使用String類型的時候,使用壓縮算法減少value大小。或者是使用Hash類型存儲,因為Hash類型底層使用了壓縮列表數(shù)據(jù)結構。

設置合理的過期時間。為每個key設置過期時間,并設置合理的過期時間,以便在數(shù)據(jù)失效后自動清理,避免長時間累積的大Key問題。

啟用內存淘汰策略。啟用Redis的內存淘汰策略,例如LRU(Least Recently Used,最近最少使用),以便在內存不足時自動淘汰最近最少使用的數(shù)據(jù),防止大Key長時間占用內存。

數(shù)據(jù)分片。例如使用Redis Cluster將數(shù)據(jù)分散到多個Redis實例,以減輕單個實例的負擔,降低大Key問題的風險。

刪除大key。使用UNLINK命令刪除大key,UNLINK命令是DEL命令的異步版本,它可以在后臺刪除Key,避免阻塞Redis實例。

七、Redis 大key如何處理?

Redis使用過程中經(jīng)常會有各種大key的情況, 比如:
單個簡單的key存儲的value很大
hash, set,zset,list 中存儲過多的元素(以萬為單位)
由于redis是單線程運行的,如果一次操作的value很大會對整個redis的響應時間造成負面影響,所以,業(yè)務上能拆則拆,下面舉幾個典型的分拆方案。

業(yè)務場景:

即通過hash的方式來存儲每一天用戶訂單次數(shù)。那么key = order_20200102, field = order_id, value = 10。那么如果一天有百萬千萬甚至上億訂單的時候,key后面的值是很多,存儲空間也很大,造成所謂的大key。

大key的風險:

  • 讀寫大key會導致超時嚴重,甚至阻塞服務。

  • 如果刪除大key,DEL命令可能阻塞Redis進程數(shù)十秒,使得其他請求阻塞,對應用程序和Redis集群可用性造成嚴重的影響。

redis使用會出現(xiàn)大key的場景:

  • 單個簡單key的存儲的value過大;
  • hash、set、zset、list中存儲過多的元素。

解決問題:

  • 單個簡單key的存儲的value過大的解決方案:

將大key拆分成對個key-value,使用multiGet方法獲得值,這樣的拆分主要是為了減少單臺操作的壓力,而是將壓力平攤到集群各個實例中,降低單臺機器的IO操作。

  • hash、set、zset、list中存儲過多的元素的解決方案:
    1).類似于第一種場景,使用第一種方案拆分;
    2).以hash為例,將原先的hget、hset方法改成(加入固定一個hash桶的數(shù)量為10000),先計算field的hash值模取10000,確定該field在哪一個key上。

將大key進行分割,為了均勻分割,可以對field進行hash并通過質數(shù)N取余,將余數(shù)加到key上面,我們取質數(shù)N為997。

那么新的key則可以設置為:

newKey = order_20200102_String.valueOf( Math.abs(order_id.hashcode() % 997) )
field = order_id
value = 10
hset (newKey, field, value) ;
hget(newKey, field)

八、 大value數(shù)據(jù)是什么,會有怎樣的問題?

當String類型的數(shù)據(jù)>10K,list、hash、set、sort set中元素個數(shù)超過1000時就可以被稱為大value,當超過100K,或集合元素個數(shù)超過10000時可以被稱為是超大value。大value最直接的影響就是有可能造成機器內存不足,就是數(shù)據(jù)傾斜;同時因為redis數(shù)據(jù)處理是單線程的,當value過大時,處理起來響應時間也會變慢。 常見的例子有:參與人數(shù)很多的蓋樓活動或者很活躍的群聊消息列表等

九、怎么處理Redis大value?

大value的處理方式還是結合業(yè)務,對其進行拆分,將其數(shù)據(jù)分布在各個redis節(jié)點中,將操作壓力平攤開,防止對單個實例IO或內存影響過大。

簡單說一下 熱點數(shù)據(jù)和大value的拆分,如果它是一個list、 set集合類型,比如原來的 為key value,value為list為拆為 list1 、list2、list3,那么新的key為 key+hash(list1)%10000 得到新的key,再對對應數(shù)據(jù)value進行set或get操作

如果是一個對象的json字符串,可以考慮將該對象的不同屬性映射到不同hash槽從而分布在不同redis節(jié)點中;或者將不同屬性拆分,利用hash結構進行存儲,從而每次處理時僅獲取一部分數(shù)據(jù)

十、總結

  • 大key和大value的危害是一致的:內存不均、阻塞請求、阻塞網(wǎng)絡。

  • key由于比value需要做更多的操作如hashcode、鏈表中比較等操作,所以會比value更多一些內存相關開銷。

  • 本文主要詳細介紹了大Key產(chǎn)生的原因、影響、檢測方法和解決方案。通過優(yōu)化數(shù)據(jù)結構設計、設定合理的數(shù)據(jù)過期策略、優(yōu)化系統(tǒng)架構和配置,以及漸進式刪除大Key等方法,我們可以有效地解決和預防大Key問題,從而提高Redis系統(tǒng)的穩(wěn)定性和性能。

到此這篇關于redis大key和大value的危害及解決的文章就介紹到這了,更多相關redis大key和大value內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家! 

相關文章

  • redis監(jiān)聽key過期事件的詳細步驟

    redis監(jiān)聽key過期事件的詳細步驟

    本文主要介紹了redis監(jiān)聽key過期事件的詳細步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2022-08-08
  • 詳解redis腳本命令執(zhí)行問題(redis.call)

    詳解redis腳本命令執(zhí)行問題(redis.call)

    這篇文章主要介紹了redis腳本命令執(zhí)行問題(redis.call),分別介紹了redis-cli命令行中執(zhí)行及l(fā)inux命令行中執(zhí)行問題,本文給大家介紹的非常詳細,需要的朋友參考下吧
    2022-03-03
  • 分布式鎖為什么要選擇Zookeeper而不是Redis?看完這篇你就明白了

    分布式鎖為什么要選擇Zookeeper而不是Redis?看完這篇你就明白了

    Zookeeper的機制可以保證分布式鎖實現(xiàn)業(yè)務代碼簡單,成本低,Redis如果要解決分布式鎖的問題,對于一些復雜的情況,很難解決,成本較高,這篇文章重點給大家介紹分布式鎖選擇Zookeeper 而不是Redis的理由,一起看看吧
    2021-05-05
  • redis實現(xiàn)sentinel哨兵架構的方法

    redis實現(xiàn)sentinel哨兵架構的方法

    哨兵是一個分布式系統(tǒng),可以在一個架構中運行多個哨兵(sentinel) 進程,這些進程使用流言協(xié)議(gossip protocols)來接收關于Master主服務器是否下線的信息,這篇文章主要介紹了redis實現(xiàn)sentinel哨兵架構,需要的朋友可以參考下
    2022-11-11
  • 一文詳解Redis在Ubuntu系統(tǒng)上的安裝步驟

    一文詳解Redis在Ubuntu系統(tǒng)上的安裝步驟

    安裝redis在Ubuntu上有多種方法,下面這篇文章主要給大家介紹了關于Redis在Ubuntu系統(tǒng)上安裝的相關資料,文中通過圖文以及代碼介紹的非常詳細,需要的朋友可以參考下
    2024-07-07
  • 基于 Redis 的 JWT令牌失效處理方案(實現(xiàn)步驟)

    基于 Redis 的 JWT令牌失效處理方案(實現(xiàn)步驟)

    當用戶登錄狀態(tài)到登出狀態(tài)時,對應的JWT的令牌需要設置為失效狀態(tài),這時可以使用基于Redis 的黑名單方案來實現(xiàn)JWT令牌失效,本文給大家分享基于 Redis 的 JWT令牌失效處理方案,感興趣的朋友一起看看吧
    2024-03-03
  • redis在Linux系統(tǒng)下的環(huán)境配置和redis的全局命令大全

    redis在Linux系統(tǒng)下的環(huán)境配置和redis的全局命令大全

    在Linux系統(tǒng)中我們經(jīng)常使用Redis作為高性能的緩存數(shù)據(jù)庫,然而有時候我們需要在系統(tǒng)中多個地方使用Redis命令,這就需要將Redis的全局命令設置好,這篇文章主要給大家介紹了關于redis在Linux系統(tǒng)下的環(huán)境配置和redis的全局命令大全的相關資料,需要的朋友可以參考下
    2024-05-05
  • Redis使用ZSET實現(xiàn)消息隊列使用小結

    Redis使用ZSET實現(xiàn)消息隊列使用小結

    這篇文章主要介紹了Redis使用ZSET實現(xiàn)消息隊列使用總結,本文通過實例代碼給大家介紹的非常詳細,需要的朋友可以參考下
    2023-03-03
  • Redis3.2.11在centos9安裝與卸載過程詳解

    Redis3.2.11在centos9安裝與卸載過程詳解

    這篇文章主要介紹了Redis3.2.11在centos9安裝與卸載過程詳解,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-01-01
  • 深度解析Redis?數(shù)據(jù)淘汰策略

    深度解析Redis?數(shù)據(jù)淘汰策略

    本文將深入剖析8種淘汰策略的機制,并結合Java代碼演示生產(chǎn)環(huán)境的最佳實踐,文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2025-04-04

最新評論