bigkey

??bigkey是指key對(duì)應(yīng)的value所占的內(nèi)存空間比較大。按照數(shù)據(jù)結(jié)構(gòu)細(xì)分,一般分為字符串類(lèi)型bigkey和非字符串類(lèi)型bigkey。

(1) 字符串類(lèi)型:一般認(rèn)為超過(guò)10KB就是bigkey。
(2) 非字符串類(lèi)型:哈希、列表、集合、有序集合,體現(xiàn)在元素個(gè)數(shù)過(guò)多。

1 bigkey的危害

??(1) 內(nèi)存使用不均勻:例如在Redis集群中,bigkey會(huì)造成節(jié)點(diǎn)的內(nèi)存空間使用不均勻。
??(2) 超時(shí)阻塞:由于Redis單線(xiàn)程的特性,操作bigkey比較耗時(shí),也就意味著阻塞Redis的可能性增大。
??(3) 網(wǎng)絡(luò)擁塞:每次獲取bigkey產(chǎn)生的網(wǎng)絡(luò)流量比較大,假設(shè)一個(gè)bigkey為1MB,每秒訪(fǎng)問(wèn)量為1000,那么每秒產(chǎn)生1000MB的流量。

2 發(fā)現(xiàn)bigkey

??redis-cli --bigkeys可以命令統(tǒng)計(jì)bigkey的分布。
??判斷一個(gè)key是否是bigkey,只需執(zhí)行debug object key查看serializedlength屬性即可,它表示key對(duì)應(yīng)的value序列化之后的字節(jié)數(shù)。
??例如如果執(zhí)行以下命令:

127.0.0.1:6379> debug object msg
Value at:000007F51306AEB0 refcount:1 encoding:raw serializedlength:31 lru:221580
4 lru_seconds_idle:10

??可以發(fā)現(xiàn)serializedlength=31 字節(jié),encoding是embstr,也就是字符串類(lèi)型,可以通過(guò)strlen看以下字符串的字節(jié)數(shù)為1675個(gè)字節(jié)。

127.0.0.1:6379> strlen msg
(integer) 1675

??serializedlength不代表真是的字符大小,它返回對(duì)象使用RDB編碼序列化后的長(zhǎng)度,值偏小。但是對(duì)于排查bigkey具有一定的輔助作用,因?yàn)椴皇敲恳环N數(shù)據(jù)結(jié)構(gòu)都有類(lèi)似strlen的命令,如列表類(lèi)型就沒(méi)有strlen命令。

127.0.0.1:6379> lpush databases mysql oracle redis
(integer) 3
127.0.0.1:6379> strlen databases
(error) WRONGTYPE Operation against a key holding the wrong kind of value

在實(shí)際生產(chǎn)環(huán)境中,發(fā)現(xiàn)bigkey的兩種方式:
(1) 被動(dòng)收集:所謂被動(dòng)收集就是等到出現(xiàn)了問(wèn)題再去分析原因,如命令的慢查詢(xún)或網(wǎng)卡跑滿(mǎn)的情況,通過(guò)分析找到可能的原因是bigkey,這種方式不推薦使用。建議修改Redis客戶(hù)端,當(dāng)拋出異常打印所操作的key,方便排查bigkey。
(2) 主動(dòng)收集:scan + debug object的命令,如果懷疑存在bigkey,可以使用scan命令漸進(jìn)的掃描出所有的key,分別計(jì)算每個(gè)key的serializedlength,找到對(duì)應(yīng)的bigkey進(jìn)行相應(yīng)的處理和報(bào)警,這種方式比較推薦。

SCAN 命令:用于迭代當(dāng)前數(shù)據(jù)庫(kù)中的數(shù)據(jù)庫(kù)鍵。跟keys命令返回全部的數(shù)據(jù)庫(kù)鍵不同,它每次執(zhí)行都只會(huì)返回少量元素,所以可以用于生產(chǎn)環(huán)境。
??SCAN 命令是一個(gè)基于游標(biāo)的迭代器(cursor based iterator): SCAN 命令每次被調(diào)用之后, 都會(huì)向用戶(hù)返回一個(gè)新的游標(biāo), 用戶(hù)在下次迭代時(shí)需要使用這個(gè)新游標(biāo)作為 SCAN 命令的游標(biāo)參數(shù), 以此來(lái)延續(xù)之前的迭代過(guò)程。

127.0.0.1:6379> scan 0
1) "13"
2)  1) "h"
    2) "e"
    3) "n"
    4) "f"
    5) "d"
    6) "s"
    7) "i"
    8) "msg"
    9) "k"
   10) "databases"
127.0.0.1:6379> scan 13
1) "0"
2) 1) "r"
   2) "t"
   3) "message"
   4) "m"
   5) "j"
   6) "l"

scan 0:第一次迭代使用 0 作為游標(biāo), 表示開(kāi)始一次新的迭代。
第二次迭代使用的是第一次迭代時(shí)返回的游標(biāo), 也即是命令回復(fù)第一個(gè)元素的值 —— 13
在第二次調(diào)用SCAN命令時(shí),命令返回了游標(biāo) 0,這表示迭代已經(jīng)結(jié)束, 整個(gè)數(shù)據(jù)集(collection)已經(jīng)被完整遍歷過(guò)了。

3 刪除bigkey

??使用del命令刪除bigkey通常來(lái)說(shuō)會(huì)阻塞Redis服務(wù)器,在生產(chǎn)環(huán)境中要盡量避免。
??當(dāng)bigkey對(duì)應(yīng)的value越來(lái)越大,刪除的時(shí)間也會(huì)隨著增加。除了string類(lèi)型刪除時(shí)一般不產(chǎn)生阻塞,其他四種數(shù)據(jù)結(jié)構(gòu)的刪除都有可能產(chǎn)生阻塞。
??刪除bigkey要使用漸進(jìn)式遍歷的方式,利用sscan、hscan、zscan命令將若干個(gè)鍵拿出來(lái)。
??實(shí)際中如何避免bigkey:

(1) 在數(shù)據(jù)結(jié)構(gòu)的選擇和設(shè)計(jì)應(yīng)合理,如出現(xiàn)了bigkey,考慮可不可以?xún)?yōu)化(例如拆分?jǐn)?shù)據(jù)結(jié)構(gòu))盡量讓bigkey消失在業(yè)務(wù)中。
(2) 如果bigkey不可避免,也要考慮是不是每次都要將所有的元素都取出來(lái),有時(shí)僅僅只需要hmget,而不是hgetall。
(3) Redis 4.0支持lazy delete free模式,刪除bigkey不會(huì)阻塞Redis。

小結(jié)

(1) bigkey會(huì)造成數(shù)據(jù)傾斜,網(wǎng)絡(luò)擁塞和超時(shí)阻塞,在實(shí)際環(huán)境中要重視bigkey。
(2) bigkey刪除要使用漸進(jìn)式遍歷方式,防止出現(xiàn)Redis阻塞的情況。
(3) Redis 4.0支持lazy delete free,它不會(huì)阻塞Redis。

??本文完


??注:本文參考《Redis開(kāi)發(fā)與運(yùn)維》,如發(fā)現(xiàn)錯(cuò)誤,請(qǐng)指正!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)載:Redis 寶典 | 基礎(chǔ)、高級(jí)特性與性能調(diào)優(yōu) 本文由 DevOpsDays 本文由簡(jiǎn)書(shū)作者kelgon供稿...
    meng_philip123閱讀 3,266評(píng)論 1 34
  • 處理bigkey bigkey是指key對(duì)應(yīng)的value所占的內(nèi)存空間比較大,例如一個(gè)字符串類(lèi)型的value可以最...
    linuxzw閱讀 2,259評(píng)論 0 3
  • 一、Python簡(jiǎn)介和環(huán)境搭建以及pip的安裝 4課時(shí)實(shí)驗(yàn)課主要內(nèi)容 【Python簡(jiǎn)介】: Python 是一個(gè)...
    _小老虎_閱讀 6,328評(píng)論 0 10
  • ORA-00001: 違反唯一約束條件 (.) 錯(cuò)誤說(shuō)明:當(dāng)在唯一索引所對(duì)應(yīng)的列上鍵入重復(fù)值時(shí),會(huì)觸發(fā)此異常。 O...
    我想起個(gè)好名字閱讀 5,962評(píng)論 0 9
  • 我寢食難安 連續(xù)兩天失魂落魄 同學(xué)們都覺(jué)得我是因?yàn)橛H眼目睹這場(chǎng)意外被嚇傻了 我鼓起勇氣 在第三天下午悄悄去了我打聽(tīng)...
    筋斗云上閱讀 106評(píng)論 0 0

友情鏈接更多精彩內(nèi)容