1. 程式人生 > >Redis 千萬不要亂用KEYS命令,不然會捱打的

Redis 千萬不要亂用KEYS命令,不然會捱打的

Redis現如今使用的場景越來越多?如何批量刪除key呢?

有人說用KEYS命令,剛開始學Redis的時候就是用這個命令列出庫中鍵。

KEYS命令要謹慎使用。

為何?客觀別急,我們先一步步來看。

KEYS 命令

Warning: consider KEYS as a command that should only be used in production environments with extreme care. It may ruin performance when it is executed against large databases. This command is intended for debugging and special operations, such as changing your keyspace layout. Don't use KEYS in your regular application code. If you're looking for a way to find keys in a subset of your keyspace, consider using sets.

上面是官方文件宣告,KEYS命令不能用在生產的環境中,這個時候如果數量過大效率是十分低的。同時也不要用KEYS正則匹配,官方建議直接用集合型別。

有人說 KEYS相當於關係性資料的庫的 select *,在生產環境幾乎是要禁用的。

  • KEYS命令的效能隨著資料庫資料的增多而越來越慢
  • KEYS命令會引起阻塞,連續的 KEYS命令足以讓 Redis 阻塞

試想如果Redis阻塞超過10秒,如果有叢集的場景,可能導致叢集判斷Redis已經故障,從而進行故障切換;

以上的情況嚴重會導致應用程式出現雪崩的情況。

然而,網上很多都是這麼寫的 redis-cli --raw keys "key字首*" | xargs redis-cli del

,千萬別照炒,拿到生產環境上做實驗。

順便普及下xargs命令,這是Linux下的一個命令 。

xargs命令是給其他命令傳遞引數的一個過濾器,也是組合多個命令的一個工具。它擅長將標準輸入資料轉換成命令列引數,xargs能夠處理管道或者stdin並將其轉換成特定命令的命令引數。xargs也可以將單行或多行文字輸入轉換為其他格式,例如多行變單行,單行變多行。xargs的預設命令是echo,空格是預設定界符。這意味著通過管道傳遞給xargs的輸入將會包含換行和空白,不過通過xargs的處理,換行和空白將被空格取代。xargs是構建單行命令的重要元件之一。

SCAN 命令

Redis從2.8版本開始支援scan命令,SCAN命令的基本用法如下:

  • 複雜度雖然也是 O(n),通過遊標分步進行不會阻塞執行緒;

  • 有限制引數 COUNT ;

  • 同 keys命令 一樣提供模式匹配功能;

  • 伺服器不需要為遊標儲存狀態,遊標的唯一狀態就是 scan 返回給客戶端的遊標整數;

scan用法

SCAN cursor [MATCH pattern] [COUNT count]
  • scan 命令提供三個引數,第一個是cursor,第二個是要匹配的正則,第三個是單次遍歷的槽位
  • 第一個遍歷是 cursor 值為0,然後將返回結果的第一個整數作為下一個遍歷的遊標,如果最後返回的到cursor的值為0就代表結束。
127.0.0.1:6379> scan 0 MATCH tony* 
1) "42"
2)  1) "tony25"
    2) "tony2519"
    3) "tony2529"
    4) "tony2510"
    5) "tony2523"
    6) "tony255"
    7) "tony2514"
    8) "tony256"
    9) "tony2511"
   10) "tony15"
127.0.0.1:6379> scan 42 MATCH tony* COUNT 1000
1) "0"
2)  1) "tony3513"
    2) "tony359"
    3) "tony4521"
    4) "tony356"
    5) "tony30"
    6) "tony320"
    7) "tony3"
    8) "tony312"

返回分為兩個部分如上面的程式碼中, 1)代表下一次迭代的遊標,2)代表本次迭代的結果集
,注意如果返回遊標為0就代表全部匹配完成。

批量刪除scan命令

因為KEYS命令的時間複雜度為O(n),而SCAN命令會將遍歷操作分解成m次,然後每次去執行,從而時間複雜度為O(1)。也解決使用keys命令遍歷大量資料而導致Redis伺服器阻塞的情況。所以建議使用下邊的指令進行批量的刪除操作:

redis-cli --scan --pattern "key字首*" | xargs -L 1000 redis-cli del

總結

因為Redis是但執行緒的KEYS在某種情況下會阻塞。有個真實真案件小哥哥生產用KEYS,最終導致服務宕機。後果很嚴重,產生的經濟損失就不說了。

切記嚴重會導致程式的雪崩,刪除的時候用SCAN命令,看完這篇文章應該都記住了。

Redis開發的建議

1、 資料分離


不要什麼都往Redis中放,儘量放些QPS比較高的資料,記憶體的開銷很昂貴的,可以考慮硬碟存放。


2、分業務

不同的例項單獨放這樣存取的時候方便些,故障的時候也不會影響其他的例項。


3、壓縮

redis中有很大的單個key的值建議壓縮成二進位制存放。


4、失效時間

redis中設定key的失效時間,如果不設定會一直佔用著記憶體,而且key的失效時間應該根據業務場景來設定。


5、容量

佔用記憶體不要太大10-20G,其次鍵的數量控制在1千萬以內。


6、監控

運維合理的監控好資料,做好Redis安全漏洞的防護和災備。