還在用keys命令模糊匹配刪除資料嗎?這就是一顆隨時**的炸彈!redis中沒有批量刪除特定字首key的指令,但我們往往需要根據字首來刪除,那麼究竟該怎麼做呢?可能你一通搜尋後會得到下邊的答案
redis-cli --raw keys "ops-coffee-*" | xargs redis-cli del
直接在linux下通過redis的keys
命令匹配到所有的key,然後呼叫系統命令xargs來刪除,看似非常完美,實則風險巨大
因為redis的單執行緒服務模式,命令keys
會阻塞正常的業務請求,如果你一次keys
匹配的數量過多或者在del
的時候遇到大key,都會直接導致業務的不可用,甚至造成redis宕機的風險
所以我們在生產環境中應當避免使用上邊的方法,那有什麼優雅的方法來解決呢?scan!
redis從2.8版本開始支援scan命令,scan命令的基本用法如下:
scan cursor [match pattern] [count count]
cursor:游標,scan命令是乙個基於游標的迭代器,scan命令每次被呼叫之後,都會向使用者返回乙個新的游標,使用者在下次迭代時需要使用這個新游標作為scan命令的游標引數,以此來延續之前的迭代過程,直到伺服器向使用者返回值為0的游標時,一次完整的遍歷過程就結束了
match:匹配規則,例如遍歷以ops-coffee-
開頭的所有key可以寫成ops-coffee-*
,中間包含-coffee-
的可以寫成*-coffee-*
count:count選項的作用就是讓使用者告知迭代命令,在每次迭代中應該從資料集裡返回多少元素,count只是對增量式迭代命令的一種提示,並不代表真正返回的數量,例如你count設定為2有可能會返回3個元素,但返回的元素資料會與count設定的正相關,count的預設值是10
以下是乙個scan命令的迭代過程示例:
127.0.0.1:6379> scan 0 match ops-coffee-*
1) "38"
2) 1) "ops-coffee-25"
2) "ops-coffee-19"
3) "ops-coffee-29"
4) "ops-coffee-10"
5) "ops-coffee-23"
6) "ops-coffee-5"
7) "ops-coffee-14"
8) "ops-coffee-16"
9) "ops-coffee-11"
10) "ops-coffee-15"
11) "ops-coffee-7"
12) "ops-coffee-1"
127.0.0.1:6379> scan 38 match ops-coffee-* count 1000
1) "0"
2) 1) "ops-coffee-13"
2) "ops-coffee-9"
3) "ops-coffee-21"
4) "ops-coffee-6"
5) "ops-coffee-30"
6) "ops-coffee-20"
7) "ops-coffee-2"
8) "ops-coffee-12"
9) "ops-coffee-28"
10) "ops-coffee-3"
11) "ops-coffee-26"
12) "ops-coffee-4"
13) "ops-coffee-31"
14) "ops-coffee-8"
15) "ops-coffee-22"
16) "ops-coffee-27"
17) "ops-coffee-18"
18) "ops-coffee-24"
19) "ops-coffee-17"
scan命令返回的是乙個包含兩個元素的陣列,第乙個陣列元素是用於進行下一次迭代的新游標,而第二個陣列元素則是乙個陣列,這個陣列中包含了所有被迭代的元素
上面這個例子的意思是掃瞄所有字首為ops-coffee-
的key
第一次迭代使用0作為游標,表示開始一次新的迭代,同時使用了match
匹配字首為ops-coffee-
的key,返回了游標值38以及遍歷到的資料
第二次迭代使用的是第一次迭代時返回的游標,也即是命令回覆第乙個元素的值38,同時通過將count選項的引數設定為1000,強制命令為本次迭代掃瞄更多元素
在第二次呼叫scan命令時,命令返回了游標0,這表示迭代已經結束,整個資料集已經被完整遍歷過了
keys命令的時間複雜度為o(n),而scan命令會將遍歷操作分解成m次時間複雜度為o(1)的操作來執行,從而解決使用keys命令遍歷大量資料而導致伺服器阻塞的情況,使用下邊的指令可以達到優雅刪除的目的:
redis-cli --scan --pattern "ops-coffee-*" | xargs -l 2000 redis-cli del
其中xargs -l
指令表示xargs一次讀取的行數,也就是每次刪除的key數量,一次讀取太多xargs會報錯
類似的scan命令,對於redis不同的資料型別還有另外幾個sscan
、hscan
和zscan
,使用方法類似:
> sscan ops-coffee 0 match v1*
1) "7"
2) 1) "v15"
2) "v13"
3) "v12"
4) "v10"
5) "v14"
6) "v1"
與scan命令不同的是這幾個命令需要多加乙個key的引數,例如上邊的ops-coffee
對於乙個大的set key,借助sscan
使用下邊的**可以實現優雅的批量刪除:
import redis
def del_big_set_key(key_name):
r = redis.strictredis(host='localhost', port=6379)
# count表示每次刪除的元素數量,這裡每次刪除300元素
for key in r.sscan_iter(name=key_name, count=300):
r.srem(key_name, key)
del_big_set_key('ops-coffee')
對於乙個大的hash key,則可借助hscan
使用下邊的**實現優雅的刪除:
import redis
def del_big_hash_key(key_name):
r = redis.strictredis(host='localhost', port=6379)
# hscan_iter獲取出來的結果是個元祖,下邊hdel刪除用key[0]取到key
for key in r.hscan_iter(name=key_name, count=300):
r.hdel(key_name, key[0])
del_big_hash_key('ops-coffee')
對於大的有序集合的刪除就比較簡單了,直接根據zremrangebyrank
排行範圍刪除
import redis
def del_big_sort_key(key_name):
r = redis.strictredis(host='localhost', port=6379)
while r.zcard(key_name) > 0:
# 判斷集合中是否有元素,如有有則刪除排行0-99的元素
r.zremrangebyrank(key_name, 0, 99)
del_big_sort_key('ops-coffee')
big list大列表的刪除可以參考上邊這個方法,通過llen
判斷數量,然後ltrim
移除範圍內的元素,這裡不贅述
至此對於redis的五中資料結構大key的優雅刪除就全部實現了,生產環境擇優使用~
redis 模糊刪除key
由於在我們的專案中使用spring cached和redis結合的方式對一部分資料做資料庫快取,當快取和資料庫資料不一致時 由於手動改資料庫引起 就得清空資料庫的快取,這就涉及到redis迷糊匹配刪除資料的情況發生。redis keys命令支援模式匹配,但是del命令不支援模式匹配,有時候需要根據一...
redis批量刪除Key
批量刪除key redis 中有刪除單個 key 的指令 del,但好像沒有批量刪除 key 的指令,不過我們可以借助 linux 的 xargs 指令來完成這個動作 redis cli keys xargs redis cli del 如果redis cli沒有設定成系統變數,需要指定redis ...
redis批量刪除key
前言 redis本身命令不提供批量刪除,但通過linux連線redis,結合redis和linux相關命令實現批量刪除。例 刪除 以employeeinfo開頭的所有資料 1.1 redis為預設埠號6379,無連線密碼,刪除命令如下 redis cli keys employeeinfo xarg...