1. 程式人生 > >Redis 4.0鮮為人知的功能將加速您的應用程式

Redis 4.0鮮為人知的功能將加速您的應用程式

來源: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,然後檢視它的效能提高。

 

更多優質中介軟體技術資訊/原創/翻譯文章/資料/乾貨,請關注“中介軟體小哥”公眾號!

&n