Redis del bigkey即使開啟了lazyfree述么,為什么還是阻塞的,但是別人又不阻塞愕掏?why

宮粽號(hào):堆棧future

Redis del bigkey之后為啥還是阻塞的呢度秘?明明開啟了lazyfree,為啥別人立馬可以刪除亭珍?


干貨:[公粽號(hào):堆棧future]

lazyfree redis 4.0引入

lazyfree-lazy-user-del 6.0引入


為什么del刪除bigkey是阻塞的

lazy-free是4.0新增的功能敷钾,但是默認(rèn)是關(guān)閉的,需要手動(dòng)開啟肄梨。你開啟之后阻荒,然后用del刪除一個(gè)幾萬(wàn)的key,發(fā)現(xiàn)命令阻塞在那里了众羡,你很郁悶侨赡,我都開啟了,為撒還阻塞呢?莫非在逗我羊壹?

先說(shuō)答案:你用錯(cuò)了命令蓖宦,在你開啟lazyfree之后,你得用redis提供的命令:unlink油猫,用這個(gè)命令去刪除就是異步了稠茂。

<pre class="custom" data-tool="mdnice編輯器" style="margin-top: 10px; margin-bottom: 10px; border-radius: 5px; box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">redis> UNLINK key1 key2 key3 (integer) 2 </pre>

源碼角度解釋下為什么

手動(dòng)開啟lazy-free時(shí),有4個(gè)選項(xiàng)可以控制情妖,分別對(duì)應(yīng)不同場(chǎng)景下睬关,要不要開啟異步釋放內(nèi)存機(jī)制:

  1. lazyfree-lazy-expire:key在過(guò)期刪除時(shí)嘗試異步釋放內(nèi)存
  2. lazyfree-lazy-eviction:內(nèi)存達(dá)到maxmemory并設(shè)置了淘汰策略時(shí)嘗試異步釋放內(nèi)存
  3. lazyfree-lazy-server-del:執(zhí)行RENAME/MOVE等命令或需要覆蓋一個(gè)key時(shí),刪除舊key嘗試異步釋放內(nèi)存
  4. replica-lazy-flush:主從全量同步毡证,從庫(kù)清空數(shù)據(jù)庫(kù)時(shí)異步釋放內(nèi)存

除了replica-lazy-flush之外电爹,其他情況都只是可能去異步釋放key的內(nèi)存,并不是每次必定異步釋放內(nèi)存的料睛。

開啟lazy-free后丐箩,Redis在釋放一個(gè)key的內(nèi)存時(shí),首先會(huì)評(píng)估代價(jià)恤煞,如果釋放內(nèi)存的代價(jià)很小屎勘,那么就直接在主線程中操作了,沒(méi)必要放到異步線程中執(zhí)行(不同線程傳遞數(shù)據(jù)也會(huì)有性能消耗)阱州。

什么情況才會(huì)真正異步釋放內(nèi)存挑秉?這和key的類型、編碼方式苔货、元素?cái)?shù)量都有關(guān)系(詳細(xì)可參考源碼中的lazyfreeGetFreeEffort函數(shù)):

  • 當(dāng)Hash/Set底層采用哈希表存儲(chǔ)(非ziplist/int編碼存儲(chǔ))時(shí)犀概,并且元素?cái)?shù)量超過(guò)64個(gè)
  • 當(dāng)ZSet底層采用跳表存儲(chǔ)(非ziplist編碼存儲(chǔ))時(shí),并且元素?cái)?shù)量超過(guò)64個(gè)
  • 當(dāng)List鏈表節(jié)點(diǎn)數(shù)量超過(guò)64個(gè)(注意夜惭,不是元素?cái)?shù)量姻灶,而是鏈表節(jié)點(diǎn)的數(shù)量,List的實(shí)現(xiàn)是在每個(gè)節(jié)點(diǎn)包含了若干個(gè)元素的數(shù)據(jù)诈茧,這些元素采用ziplist存儲(chǔ))
  • 再加一個(gè)條件就是refcount=1 就是沒(méi)有人在引用這個(gè)key的時(shí)候

只有以上這些情況产喉,在刪除key釋放內(nèi)存時(shí),才會(huì)真正放到異步線程中執(zhí)行敢会,其他情況一律還是在主線程操作曾沈。

也就是說(shuō)String(不管內(nèi)存占用多大)、List(少量元素)鸥昏、Set(int編碼存儲(chǔ))塞俱、Hash/ZSet(ziplist編碼存儲(chǔ))這些情況下的key在釋放內(nèi)存時(shí),依舊在主線程中操作吏垮。

直接看源碼:

<pre class="custom" data-tool="mdnice編輯器" style="margin-top: 10px; margin-bottom: 10px; border-radius: 5px; box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">size_t lazyfreeGetFreeEffort(robj *key, robj *obj, int dbid) { if (obj->type == OBJ_LIST) { quicklist *ql = obj->ptr; return ql->len; } else if (obj->type == OBJ_SET && obj->encoding == OBJ_ENCODING_HT) { dict *ht = obj->ptr; return dictSize(ht); } else if (obj->type == OBJ_ZSET && obj->encoding == OBJ_ENCODING_SKIPLIST){ zset *zs = obj->ptr; return zs->zsl->length; } else if (obj->type == OBJ_HASH && obj->encoding == OBJ_ENCODING_HT) { dict *ht = obj->ptr; return dictSize(ht); } else if (obj->type == OBJ_STREAM) { size_t effort = 0; stream *s = obj->ptr; } } </pre>

lazyfreeGetFreeEffort函數(shù)判斷下刪除一個(gè)key的付出有多大障涯,然后

<pre class="custom" data-tool="mdnice編輯器" style="margin-top: 10px; margin-bottom: 10px; border-radius: 5px; box-shadow: rgba(0, 0, 0, 0.55) 0px 2px 10px;">`#define LAZYFREE_THRESHOLD 64

/* Free an object, if the object is huge enough, free it in async way. */
void freeObjAsync(robj *key, robj *obj, int dbid) {
size_t free_effort = lazyfreeGetFreeEffort(key,obj,dbid);
if (free_effort > LAZYFREE_THRESHOLD && obj->refcount == 1) {
atomicIncr(lazyfree_objects,1);
bioCreateLazyFreeJob(lazyfreeFreeObject,1,obj);
} else {
decrRefCount(obj);
}
}` </pre>

它被freeObjAsync這個(gè)函數(shù)調(diào)用罐旗,用來(lái)和64去判斷并且同時(shí)判斷引用是否為1.只有滿足了大于64并且refcount==1,那么就會(huì)異步刪除唯蝶,異步刪除就是把這個(gè)刪除任務(wù)交由(bio系統(tǒng))去處理九秀,否則調(diào)用decrRefCount在主線稱中同步刪除,如果是用zmalloc申請(qǐng)的內(nèi)存最后都是調(diào)用zfree刪除粘我。

可見(jiàn)鼓蜒,即使開啟了lazy-free,String類型的bigkey涂滴,在刪除時(shí)依舊有阻塞主線程的風(fēng)險(xiǎn)友酱。所以晴音,即便Redis提供了lazy-free柔纵,我建議還是盡量不要在Redis中存儲(chǔ)bigkey

那為什么有人能del bigkey成功呢锤躁?

能del一個(gè)bigkey成功的搁料,一定是因?yàn)樗玫膔edis版本是6.0及以上的。redis增加了一個(gè)配置項(xiàng):lazyfree-lazy-user-del系羞,只要開啟了郭计,del直接可以異步刪除key了,這就和unlink沒(méi)啥區(qū)別了椒振。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末昭伸,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子澎迎,更是在濱河造成了極大的恐慌庐杨,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件夹供,死亡現(xiàn)場(chǎng)離奇詭異灵份,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)哮洽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門填渠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人鸟辅,你說(shuō)我怎么就攤上這事氛什。” “怎么了匪凉?”我有些...
    開封第一講書人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵枪眉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我洒缀,道長(zhǎng)瑰谜,這世上最難降的妖魔是什么欺冀? 我笑而不...
    開封第一講書人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮萨脑,結(jié)果婚禮上隐轩,老公的妹妹穿的比我還像新娘。我一直安慰自己渤早,他們只是感情好职车,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鹊杖,像睡著了一般悴灵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上骂蓖,一...
    開封第一講書人閱讀 52,394評(píng)論 1 310
  • 那天积瞒,我揣著相機(jī)與錄音,去河邊找鬼登下。 笑死茫孔,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的被芳。 我是一名探鬼主播缰贝,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼畔濒!你這毒婦竟也來(lái)了剩晴?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤侵状,失蹤者是張志新(化名)和其女友劉穎赞弥,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體壹将,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嗤攻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了诽俯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妇菱。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖暴区,靈堂內(nèi)的尸體忽然破棺而出闯团,到底是詐尸還是另有隱情,我是刑警寧澤仙粱,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布房交,位于F島的核電站,受9級(jí)特大地震影響伐割,放射性物質(zhì)發(fā)生泄漏候味。R本人自食惡果不足惜刃唤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望白群。 院中可真熱鬧尚胞,春花似錦、人聲如沸帜慢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)粱玲。三九已至躬柬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間抽减,已是汗流浹背允青。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留胯甩,地道東北人昧廷。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像偎箫,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子皆串,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 上篇說(shuō)到epoll解決了輪詢的方式恶复,具體是怎么解決的怜森? 在使用 select 或 poll 函數(shù)的時(shí)候,創(chuàng)建好文件...
    supremecsp閱讀 524評(píng)論 0 0
  • 以下文章來(lái)源于水滴與銀彈 谤牡,作者M(jìn)agic Kaito Redis 作為優(yōu)秀的內(nèi)存數(shù)據(jù)庫(kù)副硅,其擁有非常高的性能,單個(gè)...
    立0911閱讀 937評(píng)論 0 0
  • by shihang.mai Redis 作為優(yōu)秀的內(nèi)存數(shù)據(jù)庫(kù)翅萤,其擁有非常高的性能恐疲,單個(gè)實(shí)例的 OPS 能夠達(dá)到 ...
    麥大大吃不胖閱讀 687評(píng)論 0 0
  • 一、什么是bigkey 在Redis中套么,一個(gè)字符串最大512MB培己,一個(gè)二級(jí)數(shù)據(jù)結(jié)構(gòu)(例如hash、list胚泌、set...
    姜汁撞可樂(lè)閱讀 289評(píng)論 0 0
  • 又快到了金三銀四跳槽季玷室,好多同學(xué)已經(jīng)開始行動(dòng)了零蓉。今天我來(lái)助力一把笤受,送出這套 Redis 面試題,助力大家通關(guān)敌蜂。 R...
    Java程序員石頭閱讀 682評(píng)論 0 1