天天看點

redis 之如何通路海量資料。

如何通路Redis中海量資料,服務不會受影響?

我們知道使用keys可以找出想要的結果,但是redis有一個很關鍵的特性:單線程。keys算法是周遊算法,複雜度是0(n),資料越多時間越高。keys指令會順序執行,這将導緻線程阻塞一段時間,直到執行完畢。想象一下如果一次找出幾百萬以上的資料,執行keys指令會帶來什麼後果?卡頓,假死。如果是重要的核心業務恐怕要造成不小的損失。

 那麼我們如何去周遊大資料量呢?

redis在2.8版本以後提供了scan這個指令。

scan有什麼特點:

  • 複雜度0(n),但是它是通過遊标分步進行的,不會阻塞線程
  • 提供count參數,不是結果數量,是Redis單次周遊字典槽位數量(約等于)
  • 同keys一樣,它也提供模式比對功能
  • 伺服器不需要為遊标儲存狀态,遊标的唯一狀态就是 scan傳回給用戶端的遊标整數
  • 傳回的結果可能會有重複,需要用戶端去重,這點非常重要
  • 單詞傳回的結果是空的并不意味着周遊結束,而要看傳回的遊标值是否為0

scan 指令格式

SCAN cursor [MATCH pattern] [COUNT count]
           

scan 遊标 MATCH <傳回和給定模式相比對的元素> count 每次疊代所傳回的元素數量。

scan 指令是增量的循環,每次條用隻會反回一小部分的元素。所有不會讓Redis假死。

scan 指令傳回的是一個遊标,從0開始周遊,到0結束周遊。

舉例

127.0.0.1:6379> scan 0 match mtsu* count 10
1) "244"
2) 1) "mtsubmitid:128464154332"
   2) "mtsubmitid:128463915872"
   3) "mtsubmitid:128464745924"
   4) "mtsubmitid:128463892716"
   5) "mtsubmitid:128464775064"
   6) "mtsubmitid:128463758432"
   7) "mtsubmitid:128464611971"
           

從0開始周遊,傳回了遊标244,又傳回了資料,繼續scan周遊,就要從244開始

127.0.0.1:6379> scan 244 match mtsu* count 10
1) "390"
2) 1) "mtsubmitid:128464736797"
   2) "mtsubmitid:128464571625"
   3) "mtsubmitid:128464559272"
   4) "mtsubmitid:128464163953"
   5) "mtsubmitid:128463748985"
   6) "mtsubmitid:128464777189"
   7) "mtsubmitid:128464161014"
           

繼續閱讀