您好,登錄后才能下訂單哦!
來源:Redislabs
作者:Kyle Davis
翻譯:Kevin?(公眾號:中間件小哥)
Redis 4.0給Redis生態帶來了一個驚人的功能:Modules(模塊)。Modules是Redis的一大轉變,它是Redis內部自定義數據類型和全速計算的開放環境。但是,盡管對該版本的大多數關注都集中在Modules上,但新版本還引入了一個非常重要的命令,它就是游戲規則的改變者:UNLINK。
您可以使用redis-cli連接redis-server執行info命令,去查看當前redis版本中是否可以使用UNLINK命令。info響應將告訴您有關服務器的所有信息。在第一部分(#Server)中,返回結果有一行值為redis_version。如果該值大于4.0,則可以使用UNLINK命令。并非所有Redis提供商都保持最新版本,因此最好在更改代碼之前檢查redis版本。
讓我們回顧一下Redis的關鍵架構功能之一:“單線程”。Redis在大多數情況下是一個單線程應用程序。它一次只做一件事,這樣可以把這些事做的更快。多線程有點復雜,并且引入了鎖和其他可能降低應用程序速度的問題。盡管Redis(最高4.0版)通過多線程方式執行了少量操作,但它通常在啟動另一個命令之前先要完成一個命令。
相比于快速讀寫,您可能會覺得使用DEL命令去刪除一個鍵值不需要考慮太多,但是在很多情況下,刪除數據同樣很重要。與Redis中的大多數命令一樣,DEL命令在單個線程中運行,如果您獲取一個幾千字節的鍵值,花費不到一毫秒的時間,這是您所感知不到的。然而,當您獲取的鍵值大小是兆字節、100兆字節或者500兆字節會發生什么呢?哈希、排序、列表等數據結構會隨著時間的推移而添加更多的數據進去,這樣會生成一個數GB大小的數據集。然后用DEL命令去刪除大Key時會發生什么呢?由于Redis是單線程操作的,處理這種請求時整個服務都處于等待中,需要等待該命令執行完成才能執行其它操作。同時,我們考慮更復雜的一種場景,這些鍵中保存的數據可能已經包含數以千萬個微小請求,因此應用程序或操作員可能無法真正了解刪除這些數據需要花費多長時間。
理智會告訴我們不要在擁有100萬元素的排序集上運行如下這樣的命令:
> ZRANGE some-zset 0 -1
但是,在上面的some-zset集合中執行DEL命令將花費和上面一樣的時間-中間沒有傳輸開銷,但是它會一直去分配內存,而且您會一直卡死在CPU繁忙中。在使用UNLINK之前,您可能會結合SCAN命令采用非原子性的方法進行一些少量刪除,去避免這種持續分配內存的噩夢。上面無論使用哪種方式,都是讓人無法接受的。
您可能已經猜到了,就是使用UNLINK命令來替換DEL!從語法上講,UNLINK與DEL相同,但UNLINK提供了更為理想的解決方案。首先,它將鍵值從整個鍵值空間中刪除。然后,在另一個線程中,它開始回收內存。從多線程的角度來看,這是一種安全的操作,因為它(在主線程中)從鍵空間中刪除了該項,從而使Redis其它命令無法訪問。
如果你有一個快速增長的鍵值-不管鍵值的大小如何,UNLINK都是O(1)操作(每個鍵;在主線程中)。使用DEL刪除一個大值可能需要幾百毫秒或更長時間,而UNLINK將在不到一毫秒的時間內完成(包括網絡往返)。當然,您的服務器仍將需要花一些時間在另一個線程中重新分配該值的內存(其中的工作是O(N),其中N是已刪除值的分配數),但是主線程的性能不會被另一個線程中正在進行的操作嚴重影響到。
因此,您是否應該用UNLINK命令替換代碼中的所有DEL命令?當然,在少數情況下,DEL正是您所需要的。這里我可以想到兩點:
1、?? 在MULTI / EXEC或pipeline中,在添加和刪除大值時DEL命令是一種理想選擇。在這種情況下,UNLINK不會立即釋放空間,并且在處理繁忙的情況下(如果內存已滿),您可能會遇到麻煩。
2、?? 在更緊急的情況下,在無快速響應驅逐數據下您可以寫入數據。
在沒有極端內存限制的理想環境中,很難想到不使用UNLINK的情況。UNLINK將提供更一致的行為,總體上具有更好的性能,并且代碼更改非常小(如果可以在客戶端中重命名命令,則無需更改)。如果UNLINK適合您的應用程序,請就此將您的DEL更改為UNLINK,然后查看它的性能提高。
?
更多優質中間件技術資訊/原創/翻譯文章/資料/干貨,請關注“中間件小哥”公眾號!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。