成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

Redis隨筆-rename效率問(wèn)題

Hydrogen / 2232人閱讀

摘要:現(xiàn)象先搭建一個(gè)服務(wù)器,版本號(hào)為,看看它的內(nèi)存信息接著用給創(chuàng)建一個(gè)名為的大,有個(gè),每個(gè)的值都是這時(shí)候我們看看的內(nèi)存占用情況由于大的創(chuàng)建,內(nèi)存占用多了多兆。但其實(shí)這個(gè)不起眼的命令也可能造成一樣的問(wèn)題,使用時(shí)需要謹(jǐn)慎對(duì)待。

背景

rename是redis中給key重命名命令,rename key newkey的意思就是將key重命名為newkey。
大部分文檔在介紹rename的時(shí)候只將它描述成一個(gè)時(shí)間復(fù)雜度為O(1)的命令,卻忘了說(shuō)明它可能導(dǎo)致的性能問(wèn)題(涉及覆蓋舊值的時(shí)候 時(shí)間復(fù)雜度應(yīng)該是O(1)+O(M))。

我們先做個(gè)試驗(yàn)看看rename的問(wèn)題。

現(xiàn)象

先搭建一個(gè)redis服務(wù)器,版本號(hào)為3.2,看看它的內(nèi)存信息

127.0.0.1:8401> info memory
# Memory
used_memory:842416
used_memory_human:822.67K

接著用lua給redis創(chuàng)建一個(gè)名為 test的大key,test有500w個(gè)field,每個(gè)field的值都是1

127.0.0.1:8401> eval "for i=1,5000000,1 do redis.call("hset","test", i,1) end" 0
(nil)
(11.61s)
127.0.0.1:8401> hlen test
(integer) 5000000

這時(shí)候我們看看redis的內(nèi)存占用情況

127.0.0.1:8401> info memory
# Memory
used_memory:381185592
used_memory_human:363.53M

由于大key test的創(chuàng)建,redis內(nèi)存占用多了300多兆。
接下來(lái)我們創(chuàng)建一個(gè)臨時(shí)key,并用它來(lái)rename掉大key test

127.0.0.1:8401> set tmp 1
OK
127.0.0.1:8401> rename tmp test
OK
(2.36s)

這時(shí)就能看到執(zhí)行時(shí)間的異常了,rename執(zhí)行時(shí)間長(zhǎng)達(dá)2.36秒,這是為什么呢?我們?cè)倏纯磖edis內(nèi)存占用情況:

127.0.0.1:8401> info memory
# Memory
used_memory:821528
used_memory_human:802.27K

通過(guò)info返回的信息我們可以發(fā)現(xiàn)在執(zhí)行rename之后redis將大key test大小為300多兆的值對(duì)象直接刪除并回收掉了,而redis刪除一個(gè)key的時(shí)間復(fù)雜度是O(M),在這里M是被刪除的成員數(shù)量---500w。應(yīng)該就是這個(gè)"隱式"刪除操作導(dǎo)致了高延遲的產(chǎn)生。

文檔

我們看看官方文檔是怎么描述rename這一行為的:

RENAME key newkey

Renames?key?to?newkey. It returns an error when?key?does not exist. If?newkey?already exists it is overwritten, when this happens?RENAMEexecutes an implicit?DEL?operation, so if the deleted key contains a very big value it may cause high latency even if?RENAME?itself is usually a constant-time operation.

newkey如果本就存在,redis會(huì)用key的值覆蓋掉newkey的值,而newkey原本的值會(huì)被redis隱式地刪除。我們知道大key的刪除伴隨著高延遲(redis是單進(jìn)程服務(wù),服務(wù)器會(huì)在刪除大key期間block住接下來(lái)其他命令的執(zhí)行),這就導(dǎo)致時(shí)間復(fù)雜度本為O(1)的rename也有可能卡住redis。

這句官方文檔的原話我沒(méi)在其他文檔里找到類似的翻譯,看這些文檔的開(kāi)發(fā)者可能會(huì)誤以為這是個(gè)特別安全的O(1)命令。

既然文檔里已經(jīng)說(shuō)明了這種行為的存在,我就順便看看源碼這塊邏輯是怎么走的:

源碼分析
db.c
void renameCommand(client *c) {                                                                                        
    renameGenericCommand(c,0);
}
void renameGenericCommand(client *c, int nx) {
    robj *o;
    ...
    if ((o = lookupKeyWriteOrReply(c,c->argv[1],shared.nokeyerr)) == NULL) //舊key的值對(duì)象地址復(fù)制給o
        return;
    ...
    incrRefCount(o); //舊key的值對(duì)象引用計(jì)數(shù)+1(被o引用)
    if (lookupKeyWrite(c->db,c->argv[2]) != NULL) { //如果新key已經(jīng)有值對(duì)象了
        ...
        dbDelete(c->db,c->argv[2]); //新key從db中移除、并將新key的值對(duì)象引用計(jì)數(shù)-1(變?yōu)?),并釋放內(nèi)存
    }
    dbAdd(c->db,c->argv[2],o);  //將新key => 舊key的值對(duì)象的組合放入db中
    ...
    dbDelete(c->db,c->argv[1]); //舊key從db中移除、并將舊key的值對(duì)象引用計(jì)數(shù)-1(不會(huì)變?yōu)?),不釋放內(nèi)存
    ...
}

正常O(1)重命名的邏輯不用多說(shuō),涉及到覆蓋的過(guò)程可以簡(jiǎn)化成如下圖:

在改變指針的指向之前,redis會(huì)先用if (lookupKeyWrite(c->db,c->argv[2]) != NULL)判斷newkey是否有對(duì)應(yīng)的值,若有 則調(diào)用dbDelete(c->db,c->argv[2]);將newkey的值v2刪掉。

結(jié)論

用redis的時(shí)候,keys、 hgetall、 del 這些命令我們會(huì)多加小心,因?yàn)椴缓侠淼卣{(diào)用它們可能會(huì)長(zhǎng)時(shí)間block住redis的其他請(qǐng)求 甚至導(dǎo)致CPU使用率居高不下從而卡住整個(gè)服務(wù)器。但其實(shí)rename這個(gè)不起眼的命令也可能造成一樣的問(wèn)題,使用時(shí)需要謹(jǐn)慎對(duì)待。

參考資料

RENAME – Redis

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/29641.html

相關(guān)文章

  • php 擴(kuò)展安裝(隨筆

    摘要:查看擴(kuò)展探針擴(kuò)展相關(guān)函數(shù)管理擴(kuò)展配置下安裝流程下載對(duì)應(yīng)的版本一定要選擇正確下載擴(kuò)展的版本下載地址選擇對(duì)應(yīng)的版本版本版本在中開(kāi)啟擴(kuò)展,配置擴(kuò)展相關(guān)的參數(shù)有需要的話重啟服務(wù)器下安裝流程直裝流程把相應(yīng)的擴(kuò)展移動(dòng)到你的文件夾下面然后在中開(kāi)啟相應(yīng)的擴(kuò) 1 查看php擴(kuò)展(1)phpinfo 探針(2)php擴(kuò)展相關(guān)函數(shù)get_loaded_extensions() arrayextension...

    y1chuan 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<