Redis刪除大Key
原文連結:https://www.dubby.cn/detail.html?id=9112
>這裡說的大 key 是指包含很多元素的 set,sorted set,list 和 hash。
刪除操作,我們一般想到有 2 種,del
和expire
。
DEL
>Time complexity: O(N) where N is the number of keys that will be removed. When a key to remove holds a value other than a string, the individual complexity for this key is O(M) where M is the number of elements in the list, set, sorted set or hash. Removing a single key that holds a string value is O(1).
如果要刪除的 key 是一個集合,包含了很多元素,那麼DEL
時的耗時和元素個數成正比,所以如果直接DEL
,會很慢。
EXPIRE
>Note that calling EXPIRE/PEXPIRE with a non-positive timeout or EXPIREAT/PEXPIREAT with a time in the past will result in the key being deleted rather than expired (accordingly, the emitted key event will be del, not expired).
想著 expire 會不會可以不是直接刪除,可惜官網的描述讓我心灰意冷,如果 expire 後指定的 timeout 不是正數,也就是<=0,那其實就是DEL
。
一點一點刪
我們知道 Redis 的工作執行緒是單執行緒的,如果一個 command 堵塞了,那所有請求都會超時,這時候,一些騷操作也許可以幫助你。
其實如果想刪除 key,可以分解成 2 個目的,1:不想讓其他人訪問到這個 key,2:釋放空間。
那其實我們可以分解成兩步,先用RENAME
把原先的 key rename 成另一個 key,比如:
RENAME userInfo:123 "deleteKey:userInfo:123"
然後可以慢慢去刪"deleteKey:userInfo:123",如果是 set,那麼可以用SREM
慢慢刪,最後再用DEL
徹底刪掉。
>這裡可以搞個 task 去SCAN deleteKey:*
,然後慢慢刪除。
UNLINK
Redis 4.0.0 提供了一個更加方便的命令
>Available since 4.0.0.
>Time complexity: O(1) for each key removed regardless of its size. Then the command does O(N) work in a different thread in order to reclaim memory, where N is the number of allocations the deleted objects where composed of.
UNLINK
其實是直接返回,然後在後臺執行緒慢慢刪除。
如果你的 Redis 版本>=4.0.0,那麼強烈建議使用UNLINK
來刪除。
刪除耗時測試結果
>單位:微秒
Set 個數 | DEL | EXPIRE | UNLINK |
---|---|---|---|
1 | 90 | 97 | 75 |
10 | 79 | 67 | 100 |
100 | 51 | 49 | 47 |
1000 | 303 | 296 | 49 |
10000 | 2773 | 2592 | 52 |
100000 | 31210 | 33157 | 51 |
1000000 | 549388 | 501536 | 62 |
package main
import (
"github.com/go-redis/redis"
"fmt"
"time"
)
func main() {
client := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "",
DB: 0,
ReadTimeout: 1000 * 1000 * 1000 * 60 * 60 * 24,
WriteTimeout: 1000 * 1000 * 1000 * 60 * 60 * 24,
})
maxLength := int64(10000 * 100)
for n := int64(1); n <= maxLength; n *= 10 {
fmt.Println("Set個數", n)
TestDelBigSet(client, n)
TestExpireBigSet(client, n)
TestUnlinkBigSet(client, n)
fmt.Println()
}
}
func TestDelBigSet(client *redis.Client, count int64) {
redisKey := fmt.Sprintf("%s%d", "del:", time.Now().Nanosecond())
for n := int64(0); n < count; n++ {
err := client.SAdd(redisKey, fmt.Sprintf("%d", n)).Err()
if err != nil {
panic(err)
}
}
startTime := CurrentTimestampInMicroSecond()
client.Del(redisKey)
endTime := CurrentTimestampInMicroSecond()
fmt.Println("Del", endTime-startTime)
}
func TestUnlinkBigSet(client *redis.Client, count int64) {
redisKey := fmt.Sprintf("%s%d", "unlink:", time.Now().Nanosecond())
for n := int64(0); n < count; n++ {
err := client.SAdd(redisKey, fmt.Sprintf("%d", n)).Err()
if err != nil {
panic(err)
}
}
startTime := CurrentTimestampInMicroSecond()
client.Unlink(redisKey)
endTime := CurrentTimestampInMicroSecond()
fmt.Println("Unlink", endTime-startTime)
}
func TestExpireBigSet(client *redis.Client, count int64) {
redisKey := fmt.Sprintf("%s%d", "expire:", time.Now().Nanosecond())
for n := int64(0); n < count; n++ {
err := client.SAdd(redisKey, fmt.Sprintf("%d", n)).Err()
if err != nil {
panic(err)
}
}
startTime := CurrentTimestampInMicroSecond()
client.Expire(redisKey, 0)
endTime := CurrentTimestampInMicroSecond()
fmt.Println("Expire", endTime-startTime)
}
func CurrentTimestampInMicroSecond() int64 {
return time.Now().UnixNano() / 1000
}
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- 【Redis】 redis-cluster刪除指定的keyRedis
- 刪除大key時要小心
- 面試官:Redis中大Key怎麼刪除?面試Redis
- Redis 實用小技巧——批次刪除指定的 keyRedis
- Redis刪除特定字首key的優雅實現Redis
- Redis 刪除1.2億指定字首的keyRedis
- [轉帖]Redis中刪除過期Key的三種策略Redis
- Redis熱點key大keyRedis
- Redis 可以根據訊息儲存時長 將key 刪除嗎Redis
- 【臨實戰】使用 Python 從 Redis 中刪除 4000W 個 KEYPythonRedis
- 淺析Redis大KeyRedis
- 批量刪除 redis keysRedis
- Redis 如何處理大 KeyRedis
- redis lRem 刪除失敗?RedisREM
- redis-20.刪除策略Redis
- Redis刪除大量key後,佔用的系統記憶體卻沒有釋放?Redis記憶體
- redis 過期鍵刪除策略Redis
- Redis大key掃描Python指令碼RedisPython指令碼
- redis cluster節點/新增刪除操作Redis
- 前端刪除多條資料,如何將多個被刪除項指定key傳給後臺前端
- redis lRem 刪除失敗?(已解決)RedisREM
- Redis命令——鍵(key)Redis
- [Redis]過期刪除和記憶體淘汰Redis記憶體
- 刪除vmvare的大檔案
- python 刪除大表資料Python
- oracle大資料量分批刪除Oracle大資料
- Redis的資料被刪除,佔用記憶體咋還那麼大?Redis記憶體
- go-Redis-parser(更高效的 Redis 解析工具,支援查詢大 key)GoRedis
- 【Redis】Redis的操作命令(一)——Redis Key命令Redis
- 從Redis中刪除大集合物件的方法Redis物件
- 快速定位 Redis 熱 key?Redis
- 大資料量刪除的思考(一)大資料
- 大資料量刪除的思考(三)大資料
- 大資料量刪除的思考(四)大資料
- 大資料量刪除的思考(二)大資料
- 深度評測丨 GaussDB(for Redis) 大 Key 操作的影響Redis
- Redis 大key(bigkey)問題的排查與解決方案Redis
- 大Key