最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Redis Scan 命令使用教程(高效遍歷海量數(shù)據(jù)的方法)

 更新時(shí)間:2025年09月11日 14:19:02   作者:不想寫bug的小滕  
Scan 是 Redis 2.8 版本引入的迭代式遍歷命令,主要用于遍歷 Redis 中的鍵集合或集合類型(如 Hash、Set、Sorted Set)的元素,本文將從基礎(chǔ)介紹、實(shí)現(xiàn)原理、實(shí)操方式到實(shí)踐總結(jié),全面講解 Scan 命令的使用,感興趣的朋友跟隨小編一起看看吧

Redis 中 Scan 命令使用教程:高效遍歷海量數(shù)據(jù)

在 Redis 中,當(dāng)需要遍歷所有鍵或指定模式的鍵時(shí),傳統(tǒng)的 KEYS 命令會(huì)因阻塞主線程、無法分頁等問題,在海量數(shù)據(jù)場(chǎng)景下表現(xiàn)糟糕。而 Scan 命令憑借 “非阻塞”“分批遍歷” 的特性,成為解決大規(guī)模數(shù)據(jù)遍歷的最優(yōu)方案。本文將從基礎(chǔ)介紹、實(shí)現(xiàn)原理、實(shí)操方式到實(shí)踐總結(jié),全面講解 Scan 命令的使用。

一、介紹

Scan 是 Redis 2.8 版本引入的迭代式遍歷命令,主要用于遍歷 Redis 中的鍵集合或集合類型(如 Hash、Set、Sorted Set)的元素,核心目標(biāo)是解決傳統(tǒng)遍歷命令的性能問題。

1. 為什么需要 Scan?

傳統(tǒng)的 KEYS 命令存在明顯缺陷:

  • 阻塞主線程KEYS 會(huì)一次性遍歷所有符合條件的鍵,若數(shù)據(jù)量達(dá)百萬級(jí),會(huì)占用大量 CPU 時(shí)間,導(dǎo)致 Redis 無法響應(yīng)其他請(qǐng)求;
  • 無分頁能力KEYS 只能一次性返回所有結(jié)果,無法分批處理,容易造成客戶端內(nèi)存溢出;
  • 不支持復(fù)雜篩選:僅能通過簡(jiǎn)單的通配符(如 *?)匹配,靈活性低。

Scan 命令恰好彌補(bǔ)這些不足,具備以下核心特性:

  • 非阻塞:分批遍歷數(shù)據(jù),每次只處理少量元素,避免長(zhǎng)時(shí)間占用主線程;
  • 游標(biāo)迭代:通過 “游標(biāo)(cursor)” 記錄遍歷位置,支持?jǐn)帱c(diǎn)續(xù)傳;
  • 安全遍歷:遍歷過程中數(shù)據(jù)的新增、刪除、修改不會(huì)導(dǎo)致漏遍歷或重復(fù)遍歷(存在極小概率重復(fù),但可通過業(yè)務(wù)層去重解決);
  • 多類型支持:除了遍歷所有鍵(SCAN),還支持遍歷 Hash 字段(HSCAN)、Set 元素(SSCAN)、Sorted Set 元素(ZSCAN)。

2. 典型應(yīng)用場(chǎng)景

  • 海量鍵統(tǒng)計(jì):如統(tǒng)計(jì) Redis 中所有以 user: 為前綴的鍵數(shù)量;
  • 數(shù)據(jù)清理:分批刪除過期或無用的鍵(如刪除所有 temp: 前綴的臨時(shí)鍵);
  • 集合元素遍歷:遍歷大型 Hash 中的所有字段值,避免一次性加載導(dǎo)致內(nèi)存溢出;
  • 定期數(shù)據(jù)校驗(yàn):分批檢查鍵的過期時(shí)間或數(shù)據(jù)完整性。

二、使用原理

Scan 命令的核心是基于 “游標(biāo)” 和 “哈希表遍歷” 實(shí)現(xiàn)的,理解其底層原理能幫助更好地使用命令。

1. Redis 鍵空間的存儲(chǔ)結(jié)構(gòu)

Redis 的鍵空間(keyspace)底層基于哈希表存儲(chǔ),每個(gè)鍵通過哈希函數(shù)映射到哈希表的某個(gè) “桶(bucket)” 中。Scan 命令本質(zhì)是遍歷哈希表的桶,并通過游標(biāo)記錄當(dāng)前遍歷到的桶位置。

2. 游標(biāo)迭代機(jī)制

Scan 的遍歷過程類似 “翻書”,游標(biāo)就是 “頁碼”,具體流程如下:

  • 初始游標(biāo):首次調(diào)用 Scan 時(shí),游標(biāo)值設(shè)為 0,表示從哈希表的起始位置開始遍歷;
  • 分批遍歷:Redis 會(huì)根據(jù)游標(biāo)位置,返回當(dāng)前批次的元素(默認(rèn) 10 個(gè)),并返回新的游標(biāo)值;
  • 結(jié)束條件:當(dāng)返回的游標(biāo)值為 0 時(shí),表示已遍歷完所有元素;
  • 斷點(diǎn)續(xù)傳:若遍歷中斷(如客戶端重啟),下次可使用上次返回的非 0 游標(biāo)繼續(xù)遍歷,無需從頭開始。

3. 避免漏遍歷與重復(fù)遍歷的設(shè)計(jì)

由于 Redis 哈希表在擴(kuò)容(rehash)時(shí)會(huì)重新分配桶的位置,Scan 通過以下機(jī)制保證遍歷的準(zhǔn)確性:

  • 漸進(jìn)式 rehash 兼容:遍歷過程中若觸發(fā)哈希表擴(kuò)容,Scan 會(huì)同時(shí)遍歷舊哈希表和新哈希表,確保所有鍵都能被訪問到;
  • 允許重復(fù)遍歷:為了簡(jiǎn)化實(shí)現(xiàn),Scan 不保證元素只出現(xiàn)一次(尤其是在 rehash 過程中),但重復(fù)概率極低,業(yè)務(wù)層可通過去重(如用 Set 暫存結(jié)果)解決。

4. 計(jì)數(shù)參數(shù)(count)的作用

Scan 命令中的 count 參數(shù)用于指定 “每次遍歷的桶數(shù)量”,而非 “返回的元素?cái)?shù)量”:

  • 默認(rèn) count=10,表示每次遍歷 10 個(gè)桶,返回這些桶中的所有符合條件的元素;
  • count 并非嚴(yán)格限制,Redis 會(huì)根據(jù)桶中元素?cái)?shù)量動(dòng)態(tài)調(diào)整返回結(jié)果(如某個(gè)桶中沒有符合條件的鍵,可能返回少于 count 個(gè)元素);
  • 海量數(shù)據(jù)場(chǎng)景下,可適當(dāng)增大 count(如 count=1000),減少遍歷次數(shù),提升效率。

三、使用方式

Scan 命令家族包括 SCAN(遍歷鍵空間)、HSCAN(遍歷 Hash)、SSCAN(遍歷 Set)、ZSCAN(遍歷 Sorted Set),核心用法類似,以下以最常用的 SCAN 為例講解,其他命令用法可類比。

1. 基礎(chǔ)語法

(1)SCAN 命令(遍歷所有鍵)
 語法:SCAN cursor [MATCH pattern]  [COUNT count]  [TYPE type]
cursor:游標(biāo)值(首次為 0,后續(xù)用上次返回的游標(biāo))
MATCH pattern:通配符匹配,篩選符合條件的鍵(可選)
COUNT count:每次遍歷的桶數(shù)量(可選,默認(rèn) 10)
TYPE type:按鍵類型篩選(如 string、hash、set,可選,Redis 6.0+ 支持)
(2)其他命令語法(類比)
  • HSCAN key cursor [MATCH pattern] [COUNT count]:遍歷 Hash 鍵 key 的字段和值;
  • SSCAN key cursor [MATCH pattern] [COUNT count]:遍歷 Set 鍵 key 的元素;
  • ZSCAN key cursor [MATCH pattern] [COUNT count]:遍歷 Sorted Set 鍵 key 的元素和分?jǐn)?shù)。

2. 實(shí)操示例

(1)遍歷所有鍵(無篩選)
# 首次遍歷:游標(biāo) 0,默認(rèn) count=10
127.0.0.1:6379> SCAN 0
1) "17"  # 下次遍歷的游標(biāo)
2) 1) "user:1001"
    2) "product:2003"
    3) "order:5001"
 # 本次返回 3 個(gè)鍵(少于 count=10,因部分桶無符合條件的鍵)
# 第二次遍歷:使用上次返回的游標(biāo) 17
127.0.0.1:6379> SCAN 17
1) "0"  # 游標(biāo)為 0,遍歷結(jié)束
2) 1) "user:1002"
   2) "temp:3001"
(2)按前綴篩選鍵(MATCH)
# 遍歷所有以 "user:" 為前綴的鍵,count=20
127.0.0.1:6379> SCAN 0 MATCH user:* COUNT 20
1) "23"
2) 1) "user:1001"
    2) "user:1002"
    3) "user:1003"
# 繼續(xù)遍歷,直到游標(biāo)返回 0
127.0.0.1:6379> SCAN 23 MATCH user:* COUNT 20
1) "0"
2) 1) "user:1004"
(3)按類型篩選鍵(TYPE,Redis 6.0+)
# 遍歷所有 string 類型的鍵
127.0.0.1:6379> SCAN 0 TYPE string
1) "12"
2) 1) "user:1001"  # 假設(shè)該鍵是 string 類型
    2) "temp:3001"
(4)遍歷 Hash 鍵(HSCAN)
# 先創(chuàng)建一個(gè) Hash 鍵
127.0.0.1:6379> HMSET user:1001 name "Alice" age "25" city "Beijing"
OK
# 遍歷該 Hash 的字段和值
127.0.0.1:6379> HSCAN user:1001 0
1) "0"  # 游標(biāo)為 0,Hash 元素少,一次遍歷完
2) 1) "name"
   2) "Alice"
  3) "age"
  4) "25"
  5) "city"
  6) "Beijing"

3. 代碼示例(Golang)

以遍歷所有 user: 前綴的鍵為例,使用 go-redis 客戶端實(shí)現(xiàn):

package main
import (
	"context"
	"fmt"
	"github.com/go-redis/redis/v8"
)
func main() {
	// 初始化 Redis 客戶端
	client := redis.NewClient(&redis.Options{
		Addr:     "localhost:6379",
		Password: "",
		DB:       0,
	})
	defer client.Close()
	ctx := context.Background()
	// Scan 遍歷所有 user: 前綴的鍵
	var cursor uint64 = 0  // 初始游標(biāo)
	count := int64(20)     // 每次遍歷的桶數(shù)量
	pattern := "user:*"    // 匹配模式
	fmt.Println("開始遍歷 user: 前綴的鍵:")
	for {
		// 執(zhí)行 Scan 命令
		result, err := client.Scan(ctx, cursor, pattern, count).Result()
		if err != nil {
			fmt.Printf("Scan 執(zhí)行失?。?v\n", err)
			return
		}
		// 獲取本次結(jié)果和下次游標(biāo)
		cursor = result.Cursor
		keys := result.Keys
		// 處理本次獲取的鍵
		for _, key := range keys {
			fmt.Printf("找到鍵:%s\n", key)
		}
		// 游標(biāo)為 0,遍歷結(jié)束
		if cursor == 0 {
			break
		}
	}
	fmt.Println("遍歷完成")
}

4. 注意事項(xiàng)

  • 游標(biāo)必須正確傳遞:每次遍歷需使用上次返回的游標(biāo),否則會(huì)導(dǎo)致重復(fù)遍歷或漏遍歷;
  • 避免過度依賴 MATCHMATCH 是在遍歷結(jié)果中篩選,而非提前過濾,若符合條件的鍵極少,會(huì)導(dǎo)致多次空遍歷,建議結(jié)合業(yè)務(wù)場(chǎng)景優(yōu)化匹配模式;
  • count 參數(shù)按需調(diào)整:數(shù)據(jù)量小時(shí)用默認(rèn) count=10 即可,海量數(shù)據(jù)時(shí)可增大 count(如 1000~10000),但不宜過大(避免單次操作耗時(shí)過長(zhǎng));
  • 業(yè)務(wù)層去重:因 Scan 可能返回重復(fù)元素,需在業(yè)務(wù)層通過 Set 或哈希表去重;
  • 不建議在主庫高頻使用:雖然 Scan 非阻塞,但頻繁遍歷仍會(huì)占用 CPU 資源,建議在從庫執(zhí)行(需確保主從數(shù)據(jù)同步及時(shí))。

四、總結(jié)

Scan 命令是 Redis 中處理海量數(shù)據(jù)遍歷的核心工具,其核心優(yōu)勢(shì)可總結(jié)為:

  • 非阻塞設(shè)計(jì):分批遍歷避免阻塞主線程,保障 Redis 服務(wù)可用性;
  • 游標(biāo)迭代:支持?jǐn)帱c(diǎn)續(xù)傳,適合長(zhǎng)時(shí)間、大規(guī)模的遍歷任務(wù);
  • 靈活篩選:通過 MATCHTYPE 實(shí)現(xiàn)精準(zhǔn)篩選,滿足多樣化需求;
  • 多類型支持:覆蓋鍵空間和所有集合類型,適用場(chǎng)景廣泛。

在實(shí)際使用中,需注意以下關(guān)鍵要點(diǎn):

  • 正確傳遞游標(biāo),確保遍歷的連續(xù)性;
  • 根據(jù)數(shù)據(jù)量調(diào)整 count 參數(shù),平衡遍歷效率和資源占用;
  • 結(jié)合業(yè)務(wù)場(chǎng)景優(yōu)化篩選邏輯,減少無效遍歷;
  • 對(duì)遍歷結(jié)果進(jìn)行去重,避免重復(fù)處理。

總之,Scan 命令徹底解決了傳統(tǒng) KEYS 命令的性能痛點(diǎn),是 Redis 運(yùn)維和開發(fā)中處理海量數(shù)據(jù)的 “必備工具”,掌握其用法能顯著提升大規(guī)模 Redis 集群的管理效率。

到此這篇關(guān)于Redis Scan 命令使用教程(高效遍歷海量數(shù)據(jù)的方法)的文章就介紹到這了,更多相關(guān)Redis Scan 命令使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Redis內(nèi)部數(shù)據(jù)結(jié)構(gòu)Dict的實(shí)現(xiàn)方法

    Redis內(nèi)部數(shù)據(jù)結(jié)構(gòu)Dict的實(shí)現(xiàn)方法

    這篇文章主要介紹了Redis內(nèi)部數(shù)據(jù)結(jié)構(gòu)Dict的實(shí)現(xiàn)方法,本篇文章所述的dict在Redis中最主要的作用就是用于維護(hù)Redis數(shù)據(jù)庫中所有Key、value映射的數(shù)據(jù)結(jié)構(gòu),需要的朋友可以參考下
    2022-05-05
  • redis初學(xué)者常見字符亂碼問題及解決方案

    redis初學(xué)者常見字符亂碼問題及解決方案

    這篇文章主要介紹了redis初學(xué)者常見字符亂碼問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • 高并發(fā)技巧之Redis和本地緩存使用技巧分享

    高并發(fā)技巧之Redis和本地緩存使用技巧分享

    在這篇文章中,我主要介紹的是分布式緩存和本地緩存的使用技巧,包括緩存種類介紹,各種的使用場(chǎng)景,以及如何使用,最后再給出實(shí)戰(zhàn)案例,需要的可以參考一下
    2022-10-10
  • redis實(shí)現(xiàn)排行榜的簡(jiǎn)單方法

    redis實(shí)現(xiàn)排行榜的簡(jiǎn)單方法

    這篇文章主要給大家介紹了關(guān)于redis實(shí)現(xiàn)排行榜的簡(jiǎn)單方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-08-08
  • Redis事務(wù)處理的使用操作方法

    Redis事務(wù)處理的使用操作方法

    Redis保證一個(gè)事務(wù)中的所有命令要么都執(zhí)行,要么都不執(zhí)行(原子性),如果客戶端發(fā)送了EXEC命令,所有的命令就都會(huì)被執(zhí)行,即使此后客戶端斷線也沒關(guān)系,因?yàn)镽edis中已經(jīng)記錄了所有要執(zhí)行的命令,下面通過本文給大家介紹Redis事務(wù)處理的使用操作,感興趣的朋友一起看看吧
    2021-10-10
  • Redis內(nèi)存滿了的幾種原因和最佳解決方案

    Redis內(nèi)存滿了的幾種原因和最佳解決方案

    Redis是一款高性能的內(nèi)存數(shù)據(jù)庫,被廣泛應(yīng)用于緩存、消息隊(duì)列、計(jì)數(shù)器等場(chǎng)景,然而,由于Redis是基于內(nèi)存的數(shù)據(jù)庫,當(dāng)數(shù)據(jù)量過大或者配置不合理時(shí),就有可能導(dǎo)致Redis的內(nèi)存滿,本文將介紹Redis內(nèi)存滿的幾種原因,并提供相應(yīng)的解決方案,需要的朋友可以參考下
    2023-11-11
  • Redis鎖的過期時(shí)間小于業(yè)務(wù)的執(zhí)行時(shí)間如何續(xù)期

    Redis鎖的過期時(shí)間小于業(yè)務(wù)的執(zhí)行時(shí)間如何續(xù)期

    本文主要介紹了Redis鎖的過期時(shí)間小于業(yè)務(wù)的執(zhí)行時(shí)間如何續(xù)期,Redisson它能給Redis分布式鎖實(shí)現(xiàn)過期時(shí)間自動(dòng)續(xù)期,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-05-05
  • 在Redis中如何保存時(shí)間序列數(shù)據(jù)詳解

    在Redis中如何保存時(shí)間序列數(shù)據(jù)詳解

    與發(fā)生時(shí)間相關(guān)的一組數(shù)據(jù),就是時(shí)間序列數(shù)據(jù),這些數(shù)據(jù)的特點(diǎn)是沒有嚴(yán)格的關(guān)系模型,記錄的信息可以表示成鍵和值的關(guān)系,這篇文章主要給大家介紹了關(guān)于在Redis中如何保存時(shí)間序列數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • redis持久化AOF和RDB的區(qū)別及解決各個(gè)場(chǎng)景問題示例

    redis持久化AOF和RDB的區(qū)別及解決各個(gè)場(chǎng)景問題示例

    這篇文章主要為大家介紹了redis持久化AOF和RDB的區(qū)別及解決各個(gè)場(chǎng)景問題示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Redis如何解決BigKey

    Redis如何解決BigKey

    在Redis的使用過程中,我們經(jīng)常會(huì)遇到BigKey, BigKey的大值會(huì)導(dǎo)致Redis內(nèi)存中產(chǎn)生大量不連續(xù)的碎片,降低內(nèi)存利用效率,本文主要介紹了Redis如何解決BigKey,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01

最新評(píng)論

常宁市| 卓资县| 名山县| 固原市| 东乡族自治县| 美姑县| 民权县| 孟连| 上犹县| 托克逊县| 太湖县| 中卫市| 太仓市| 通化县| 兴业县| 芒康县| 高淳县| 十堰市| 色达县| 白河县| 山西省| 古蔺县| 大姚县| 峨边| 昌邑市| 富蕴县| 兴国县| 洞头县| 光山县| 昌都县| 拉孜县| 隆化县| 响水县| 郎溪县| 苍溪县| 宜州市| 滨州市| 太和县| 凌源市| 彩票| 廊坊市|