欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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ì)因阻塞主線程、無(wú)法分頁(yè)等問題,在海量數(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á)百萬(wàn)級(jí),會(huì)占用大量 CPU 時(shí)間,導(dǎo)致 Redis 無(wú)法響應(yīng)其他請(qǐng)求;
  • 無(wú)分頁(yè)能力KEYS 只能一次性返回所有結(jié)果,無(wú)法分批處理,容易造成客戶端內(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ù)清理:分批刪除過期或無(wú)用的鍵(如刪除所有 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)就是 “頁(yè)碼”,具體流程如下:

  • 初始游標(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ù)遍歷,無(wú)需從頭開始。

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ǔ)語(yǔ)法

(1)SCAN 命令(遍歷所有鍵)
 語(yǔ)法: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)其他命令語(yǔ)法(類比)
  • 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)遍歷所有鍵(無(wú)篩選)
# 首次遍歷:游標(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,因部分桶無(wú)符合條件的鍵)
# 第二次遍歷:使用上次返回的游標(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 或哈希表去重;
  • 不建議在主庫(kù)高頻使用:雖然 Scan 非阻塞,但頻繁遍歷仍會(huì)占用 CPU 資源,建議在從庫(kù)執(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)化篩選邏輯,減少無(wú)效遍歷;
  • 對(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)文章

  • hiredis從安裝到項(xiàng)目實(shí)戰(zhàn)操作

    hiredis從安裝到項(xiàng)目實(shí)戰(zhàn)操作

    這篇文章主要介紹了hiredis從安裝到項(xiàng)目實(shí)戰(zhàn)操作,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-02-02
  • 基于redis實(shí)現(xiàn)分布式鎖的原理與方法

    基于redis實(shí)現(xiàn)分布式鎖的原理與方法

    這篇文章主要給大家介紹了基于redis實(shí)現(xiàn)分布式鎖的原理與方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用redis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Redis 操作多個(gè)數(shù)據(jù)庫(kù)的配置的方法實(shí)現(xiàn)

    Redis 操作多個(gè)數(shù)據(jù)庫(kù)的配置的方法實(shí)現(xiàn)

    本文主要介紹了Redis 操作多個(gè)數(shù)據(jù)庫(kù)的配置的方法實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • 關(guān)于Redis最常見的十道面試題總結(jié)大全

    關(guān)于Redis最常見的十道面試題總結(jié)大全

    Redis作為一個(gè)高性能的內(nèi)存數(shù)據(jù)存儲(chǔ)系統(tǒng),具有快速讀寫、持久性、數(shù)據(jù)結(jié)構(gòu)多樣性等特點(diǎn),廣泛應(yīng)用于各種應(yīng)用場(chǎng)景,這篇文章主要給大家介紹了關(guān)于Redis最常見的十道面試題總結(jié)的相關(guān)資料,需要的朋友可以參考下
    2024-07-07
  • Redis中如何設(shè)置日志

    Redis中如何設(shè)置日志

    這篇文章主要介紹了Redis中如何設(shè)置日志問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • Redis請(qǐng)求處理的流程分析

    Redis請(qǐng)求處理的流程分析

    這篇文章主要介紹了Redis?是如何進(jìn)行請(qǐng)求處理,這篇文章介紹了整個(gè)?Redis?的請(qǐng)求處理模型到底是怎樣的。從注冊(cè)監(jiān)聽?fd?事件到執(zhí)行命令,到最后將數(shù)據(jù)回寫給客戶端都做了個(gè)大概的分析,需要的朋友可以參考下
    2022-07-07
  • Redis做數(shù)據(jù)持久化的解決方案及底層原理

    Redis做數(shù)據(jù)持久化的解決方案及底層原理

    Redis有兩種方式來(lái)實(shí)現(xiàn)數(shù)據(jù)的持久化,分別是RDB(Redis Database)和AOF(Append Only File),今天通過本文給大家聊一聊Redis做數(shù)據(jù)持久化的解決方案及底層原理,感興趣的朋友一起看看吧
    2021-07-07
  • Redis過期監(jiān)聽機(jī)制,訂單超時(shí)自動(dòng)取消方式

    Redis過期監(jiān)聽機(jī)制,訂單超時(shí)自動(dòng)取消方式

    這篇文章主要介紹了Redis過期監(jiān)聽機(jī)制,訂單超時(shí)自動(dòng)取消方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Redis 集群搭建和簡(jiǎn)單使用教程

    Redis 集群搭建和簡(jiǎn)單使用教程

    集群技術(shù)是構(gòu)建高性能網(wǎng)站架構(gòu)的重要手段,下面這篇文章主要介紹了Redis 集群搭建和簡(jiǎn)單使用教程,文中通過示例代碼和圖片介紹的很想,對(duì)大家具有一定的參考價(jià)值,有需要的朋友們下面來(lái)一起看看吧。
    2017-02-02
  • Redis分布式鎖的正確實(shí)現(xiàn)方法總結(jié)

    Redis分布式鎖的正確實(shí)現(xiàn)方法總結(jié)

    在本篇文章里小編給大家整理的是關(guān)于Redis分布式鎖的正確實(shí)現(xiàn)方式介紹,有興趣的朋友們可以學(xué)習(xí)下。
    2020-02-02

最新評(píng)論