天天看點

如何通路redis中的海量資料目錄前言事故産生分析原因解決方案

目錄

  1. 前言
  2. 事故産生
  3. 分析原因
  4. 解決方案
  5. 總結

前言

有時候我們需要知道線上的redis的使用情況,尤其需要知道一些字首的key值,那我們怎麼去檢視呢?

事故産生

因為我們的使用者token緩存是采用了【user_token:userid】格式的key,儲存使用者的token的值。

我們運維為了幫助開發小夥伴們查一下線上現在有多少登入使用者,直接用了keys user_token*方式進行查詢。

事故就此發生了。導緻redis不可用,假死。

分析原因

我們線上的登入使用者有幾百萬,資料量比較多;keys算法是周遊算法,複雜度是O(n),也就是資料越多,時間複雜度越高。

資料量達到幾百萬,keys這個指令就會導緻 Redis 服務卡頓

因為 Redis 是單線程程式,順序執行所有指令,其它指令必須等到目前的 keys 指令執行完了才可以繼續。

解決方案

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

這個也是面試經常問的。我們可以采用redis的另一個指令scan。我們看一下scan的特點

1、複雜度雖然也是 O(n),但是它是通過遊标分步進行的,不會阻塞線程

2、提供 count 參數,不是結果數量,是redis單次周遊字典槽位數量(約等于)

3、同 keys 一樣,它也提供模式比對功能;

4、伺服器不需要為遊标儲存狀态,遊标的唯一狀态就是 scan 傳回給用戶端的遊标整數;

5、傳回的結果可能會有重複,需要用戶端去重複,這點非常重要;

6、單次傳回的結果是空的并不意味着周遊結束,而要看傳回的遊标值是否為零

一、scan指令格式

SCAN cursor [MATCH pattern] [COUNT count]

二、指令解釋:scan 遊标 MATCH <傳回和給定模式相比對的元素> count 每次疊代所傳回的元素數量

SCAN指令是增量的循環,每次調用隻會傳回一小部分的元素。是以不會讓redis假死

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

三、舉例

redis > scan 0 match user_token* count 5

1) "6"

2) 1) "user_token:1000"

2) "user_token:1001"

3) "user_token:1010"

4) "user_token:2300"

5) "user_token:1389"

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

redis > scan 6 match user_token* count 5

1) "10"

2) 1) "user_token:3100"

2) "user_token:1201"

3) "user_token:1410"

4) "user_token:5300"

5) "user_token:3389"

繼續閱讀