php redis批量刪除keys的方法:首先打開命令窗口;然后通過命令“redis-cli keys video* | xargs redis-cli del”實現(xiàn)批量刪除key即可。
redis實現(xiàn)批量刪除key功能
推薦:《PHP視頻教程》
keys
在測試環(huán)境使用redis的時候,經常會要批量刪除key,我們但是redis并沒有提供批量刪除的命令,但是我們可以在命令行下,使用keys遍歷鍵實現(xiàn)
//批量刪除以video開頭的key redis-cli keys video* | xargs redis-cli del //以j,r開頭,緊跟edis字符串的所有鍵 redis-cli keys [j,r]edis | xargs redis-cli del
注意: redis是單線程架構,如果redis包含了大量的鍵,執(zhí)行keys命令可能會造成redis阻塞,所以一般建議不要在生產環(huán)境下使用keys命令。 如果非要遍歷鍵刪除的話,可以在一下三種情況使用: (1)在一個不對外提供服務的Redis從節(jié)點上執(zhí)行,這樣不會阻塞到客戶端的請求,但是會影響到主從復制。 (2)如果確認鍵值總數(shù)確實比較少,可以執(zhí)行該命令。 (3)使用scan命令漸進式的遍歷所有鍵,可以有效防止阻塞。
漸進式遍歷
scan命令文檔
Redis提供了面向哈希類型、集合類型、有序集合的掃描遍歷命令,解決諸如hgetall、smembers、zrange可能產生的阻塞問題,對應的命令分別是hscan、sscan、zscan,它們的用法和scan基本類似。
注意:
漸進式遍歷可以有效的解決keys命令可能產生的阻塞問題,但是scan并非完美無瑕,如果在scan的過程中如果有鍵的變化(增加、刪除、修改),
那么遍歷效果可能會碰到如下問題:新增的鍵可能沒有遍歷到,遍歷出了重復的鍵等情況,也就是說scan并不能保證完整的遍歷出來所有的鍵,這些是我們在開發(fā)時需要考慮的。
<?php namespace Redis; use Redis; class RedisTest { const PORT = 6379; /** * redis對象 */ public $redis = null; public function __construct() { $this->redis = new Redis(); $this->redis->connect('127.0.0.1', self::PORT); } public function info() { print_r($this->redis->info()); } /** * 刪除前綴是test:的key */ public function keyDelete() { $pre = 'test:'; for ($i = 0; $i < 10; $i++) { $this->redis->set($pre . "$i", "$i"); } // Have scan retry $this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); $it = NULL; while ($arr_keys = $this->redis->scan($it, "$pre*", 5)) { call_user_func_array([$this->redis, 'del'], $arr_keys); echo var_export($arr_keys, true) . PHP_EOL; } } }
返回結果
array ( 0 => 'test:8', ) array ( 0 => 'test:1', ) array ( 0 => 'test:9', ) array ( 0 => 'test:6', ) array ( 0 => 'test:5', ) array ( 0 => 'test:0', ) array ( 0 => 'test:3', ) array ( 0 => 'test:7', ) array ( 0 => 'test:4', ) array ( 0 => 'test:2', )
SSCAN、HSCAN、ZSCAN、SCAN命令的坑
// Have scan retry $this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); $it = NULL; while ($arr_keys = $this->redis->scan($it, "$pre*", 5)) { call_user_func_array([$this->redis, 'del'], $arr_keys); echo var_export($arr_keys, true) . PHP_EOL; }
根據(jù)scan的文檔說明可知:scan命令每次迭代的時候,有可能返回空,但這并不是結束的標志,而是當返回的迭代的值為”0″時才算結束。
因此,上面的代碼在迭代的時候,若沒有arr_keys返回,$arr_keys是個空數(shù)組,所以while循環(huán)自然就中斷了,所以沒有任何輸出。
為了避免arr_keys返回是個空數(shù)組的問題我們可以這樣解決:
解決方法一
$this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY);
告訴redis擴展,當執(zhí)行scan命令后,返回的結果集為空的話,函數(shù)不返回,而是直接繼續(xù)執(zhí)行scan命令。這樣當scan函數(shù)返回的時候,要么返回false,即迭代結束。
注意:SSCAN、HSCAN、ZSCAN也是一樣的邏輯
解決方法二
//方式一 // Have scan retry $this->redis->setOption(Redis::OPT_SCAN, Redis::SCAN_RETRY); $it = NULL; while ($arr_keys = $this->redis->scan($it, "$pre*", 5)) { call_user_func_array([$this->redis, 'del'], $arr_keys); echo var_export($arr_keys, true) . PHP_EOL; } //方式二 while (true) { $arr_keys = $this->redis->scan($it, "$pre*"); if ($arr_keys === false) {//迭代結束,未找到匹配pattern的key return; } call_user_func_array([$this->redis, 'del'], $arr_keys); echo var_export($arr_keys, true) . PHP_EOL; }