Redis簡單實踐 掃瞄指令scan

2022-07-18 03:45:09 字數 1807 閱讀 9974

redis在應用中的存在一般是以快取的形式,但是在某些應用場景也可能會涉及到需要拿出大量keys的情況,一般全盤掃瞄只需要使用keys *就可以拿出所有的key,但是keys指令有很明顯的缺陷。

1.沒有sql中類似offset等指令,無法分批

2.keys是直接遍歷,複雜度o(n),全表數量大會造成整個redis的卡頓

在redis中,能夠實現以上要求的則是scan,scan和keys最大區別就在於,scan可以分批取資料,類似sql中的分頁,總結來說scan有以下幾個特點:

1.複雜度是o(n),但是scan通過游標分步進行,不會卡執行緒

2.提供limit引數,可控制每次返回的條數,但是並不保證一定會返回對應條數,或多或少,這個和redis儲存的hashmap結構有關

3.和keys一樣,提供了匹配選項

4.通過游標儲存狀態

5.返回結果在某些條件下會有重複,這個主要是存在於擴容遷移的時候

6.在游標繼續向下遍歷的途中,加入有修改或者新增的資料,並不保證一定能遍歷到

7.遍歷結束的依據和返回的資料數量無關,只和游標有關,游標為0時表示結束

scan的基本語法是scan cursor [match pattern][count count]

可以看到通過傳入count引數可以將返回的資料控制,但是返回的資料個數並不一定是傳入count,對於redis來說,傳入的count只是乙個提示,告知redis掃瞄的個數(這個在文章尾部有介紹)。

同時在上圖中,我們的redis一共有1000個key,在第三張圖中可以看到,但我們的count>key個數的時候,返回的第乙個結果的值是「0」,而0也代表著本次掃瞄已經將redis符合條件的key全部掃瞄完成,而不為0則表示還有剩餘的資料可以繼續掃瞄,如下圖所示,帶入第一張圖中的「64」:

首先我們明確,在redis中,資料是以hashmap的形式存在,如下圖所示:

而scan指令返回的游標就是其中一維陣列的位置的索引,詳細參考redis底層原理-key儲存結構中所作的介紹,在正常的邏輯(redis不存在擴容縮容等等)情況下,scan直接按照陣列的下標進行遍歷,limit則是需要掃瞄的陣列的下標個數,返回的數量則是由陣列每個下標對應的鍊錶中能夠匹配到多少資料為準,下面兩個圖在我們傳入match引數時候顯得更加明顯:

在redis中,scan除了遍歷普通的key以外,還可以針對性的對其他基礎資料結構進行遍歷,比如zscan對應zset集合元素,hscan對應hash的元素,sscan對應set集元素,他們的原理和scan相同,例如hash底層使用了字典的資料結構,zset則是乙個value指向同乙個元素的特殊hash,zset也使用字典結構來儲存所有的元素內容。

hibernate SQLQuery實踐指南

兩個表 實體 1對多雙向關聯 班級 clazz id,name 學生 student id,name class id 1.1 簡單查詢,返回資料庫結構 view plain copy to clipboard print?sql?select?c.from?clazz?c,student?s?wh...

hibernate SQLQuery實踐指南

hibernate sqlquery實踐指南 兩個表 實體 1對多雙向關聯 班級 clazz id,name 學生 student id,name class id 1.查詢持久化物件 1.1 簡單查詢,返回資料庫結構 sql select c.from clazz c,student s wher...

redis實踐小結

redis 安裝高階一 wget tar xzf redis 5.0.5.tar.gz cd redis 5.0.5 make啟動服務端 使用預設引數 src redis server使用內建的客戶端 src redis cli redis set foo bar okredis get foo b...