Redis 實用小技巧—— key 分佈情況分析

快樂的皮拉夫發表於2023-05-09

背景

在實際生產中,隨著業務體系越來越龐大,Redis 的使用量也會隨之上升,當 Redis 資料庫變的越來越大時,我們經常會遇到以下幾種問題:

  1. key 的資料型別分佈問題:型別使用是否合理?
  2. key 的儲存空間佔用問題:是否存在一定數量的 bigkey ?
  3. key 的過期時間問題:是否存在大量未設定過期的 key ?key 是否存在集中過期的情況?

從上述問題不難看出,此類場景下我們並非關注的是具體的某個 key ,而是 key 的一個整體分佈的情況。下面我們就針對這些問題來看看具體應該如何解決。

方案

rdbtools 是一款 Redis rdb 分析工具,可以透過 rdb 檔案生成記憶體報告。因此,我們可以考慮藉助這個工具來解決上述場景出現的問題。

步驟一:安裝 python3

rdbtools 依賴 python3 版本,如果系統有預裝的 python2 版本,可使用以下方法先進行解除安裝,然後再重新安裝。

1. 強制解除安裝舊版本的 python (以 Linux 為例):
rpm -qa|grep python|xargs rpm -ev --allmatches --nodeps
whereis python |xargs rm -frv
whereis python
2. 下載原始碼壓縮包
wget https://www.python.org/ftp/python/3.9.9/Python-3.9.9.tgz
3. 編譯準備工作
mkdir -p /usr/local/python3
tar -zxvf Python-3.9.9.tgz 
cd Python-3.9.9.tgz
./configure --prefix=/usr/local/python3 
4. 編譯安裝
$ make && make install
5. 設定軟連線
ln -s /usr/local/python3/bin/pip3 /usr/bin/pip
ln -s /usr/local/python3/bin/python3 /usr/bin/python
6. 配置環境變數

首先開啟環境變數配置檔案:

vim /etc/profile

新增以下配置:

export PATH=$PATH:/usr/local/python3/bin

然後重新載入環境變數。

source /etc/profile

到這裡 python3 就已經安裝好了,命令列輸入:

python --version
pip --version

如果可以看到版本資訊的話,說明 python3 和 pip3 已經安裝成功。

步驟二:安裝 rdbtool

1. 升級 pip 版本

如果提示 pip 版本過低問題,可按照下面命令進行升級:

/usr/bin/python3 -m pip install --upgrade pip
2. 升級 setuptools 版本

如果提示 setuptools 版本過低問題,可按照下面命令進行升級:

pip3 install --upgrade setuptools
3. 安裝rdbtools
pip install rdbtools python-lzf

安裝完成以後,命令列下輸入以下命令,如果出現幫助提示,證明安裝成功。

rdb --help

步驟三:生成 rdb 檔案

這裡我們分別介紹如何從本地和雲端生成 rdb 檔案。

本地伺服器生成 rdb 檔案

1. 修改 Redis 配置檔案

透過以下命令檢視 Redis 配置檔案位置:

redis-cli info server | grep config_file

修改 rdb 檔案的名稱和儲存位置(儲存位置可自定義,具有操作許可權即可)。

vim /usr/local/redis/etc/redis.conf

指定 rdb 檔案的名稱和路徑。

dbfilename 6379.rdb
dir /usr/local/redis/data/

修改完配置以後,需要重啟 Redis 伺服器。

2. 動態修改 Redis 配置

動態修改 Redis 配置是在不重啟 Redis 服務的情況下直接生效(重啟 Redis 服務會導致服務短暫不可用或資料丟失)

redis-cli CONFIG SET "dbfilename" "6379.rdb"
redis-cli CONFIG SET "dir" "/usr/local/redis/data/"

1 和 2 步驟選擇一種執行即可,不必重複執行。

3. 生成 rdb 檔案
redis-cli BGSAVE

執行完命令後會在配置的路徑下生成二進位制的 rdb 檔案。

阿里雲 Redis 服務獲取 rdb 檔案

阿里雲 Redis 在以下位置進行下載即可。

阿里雲 Redis 服務獲取 rdb 檔案

步驟四:分析資料

分析資料之前我們先來了解一下 rdb 命令的用法。

rdb [options] /path/to/dump.rdb

例如: rdb --command json -k "user.*" /var/redis/6379/dump.rdb

其中 rdb 檔案路徑為必傳引數,其他可選的引數如下所示:

短引數 長引數 描述
-h –help 顯示幫助資訊
-c CMD –command CMD 可執行的命令。有效的命令包括:jsondiffjustkeysjustkeyvalsmemoryprotocol
-f FILE –file FILE 輸出檔案
-n DBS –db DBS 資料庫編號。可以提供多個資料庫編號,如果預設將處理所有資料庫的資料
-k KEYS –key KEYS 匯出的鍵。可以是正規表示式
-o NOT_KEYS –not-key NOT_KEYS 不匯出的鍵。可以是正規表示式
-t TYPES –type TYPES 匯出鍵的型別。支援的型別有:stringhashsetsortedsetlist。支援提供多個型別匯出,預設則匯出所有型別
-b BYTES –bytes BYTES 僅輸出大於或等於指定值的鍵
-l LARGEST –largest LARGEST 僅輸出記憶體排名前N的鍵
-e {raw,print,utf8,base64} –escape {raw,print,utf8,base64} 字串編碼格式
-x –no-expire 透過協議命令排除過期的鍵
-a N –amend-expire N 透過協議命令給鍵增加N秒的過期時間

瞭解了 rdb 的基本使用,就可以藉助它生成分析檔案了。接下來介紹如何生成分析檔案和常見問題的處理。

生成分析檔案命令如下(這裡以 memory 命令為例,生成 csv 格式的分析檔案):

rdb -c memory -f 6379.csv /usr/local/redis/data/6379.rdb

檢視生成的分析報告:

cat 6379.csv

檔案內容如下:

  database,type,key,size_in_bytes,encoding,num_elements,len_largest_element,expiry 
  0,hash,foo-4,83,ziplist,3,2,
  0,sortedset,foo-6,83,ziplist,4,2,
  0,list,foo-7,163,quicklist,6,2,
  0,set,foo-5,396,hashtable,5,2, 
  0,string,foo-1,56,string,5,5,
  0,string,foo-2,56,string,5,5, 
  0,string,foo-3,88,string,5,5,2022-07-02T12:46:09.122000

可以看到,用工具轉化成 csv 檔案後,會劃分成 8 個列,分別是:

列名稱 含義
database 資料庫編號
type 資料型別
key
size_in_bytes 使用的記憶體:包括鍵、值和其他任何開銷
encoding RDB 編碼型別
num_elements 鍵中元素的個數
len_largest_element 最大元素的長度
expiry 過期時間

有了這些資訊,下一步就是如何藉助這些資訊來解決我們開頭提到的那些問題了。可以透過 rdb 自帶的引數實現,也可以藉助外部的工具或者命令實現。

問題一:查詢所有未設定過期的鍵
rdb -c justkeys -x /usr/local/redis/data/6379.rdb
問題二:查詢各資料型別的鍵的分佈

統計資料庫中字串型別的鍵的個數

rdb -c justkeys -t string /usr/local/redis/data/6379.rdb | wc -l
問題三:查詢佔記憶體最大的前 N 個鍵
rdb -c memory -l {N} /usr/local/redis/data/6379.rdb

說明:
使用 redis-cli --bigkeys 也可以統計 Redis 的大 key ,但是該命令只能統計每種資料型別下佔記憶體最大的 key ,如果需要找出限制大小條件的大 key ,使用此命令就不合適了。但是此命令還具有生成記憶體分析報告( summary )的功能,可以生成鍵記憶體使用情況的分析報告,在一些情況下也可以幫助分析 Redis 的記憶體佔用情況。

問題四:查詢某個字首的所有的鍵
rdb -c justkeys -k "{keyname}" /usr/local/redis/data/6379.rdb

在生產環境需要批次對特定的鍵進行操作時,如果僅知道鍵的字首的話,可以採用此種方法先獲取到所有符合條件的鍵,然後再透過指令碼進行處理,能夠大大提高處理效率。

問題五:檢視某個鍵佔用記憶體的大小
$ rdb -c memory -k "{keyname}" /usr/local/redis/data/6379.rdb

也可以透過 redis-memory-for-key(安裝 rdbtools 工具時會預設安裝這個工具)這個工具直接檢視鍵的佔用記憶體的大小,更加快捷方便,使用該命令無須生成 rdb 檔案,可以直接連線redis伺服器進行檢視。具體用法如下:

redis-memory-for-key {keyname}

輸出結果如下:

  Key           keyname
  Bytes             56
  Type          string

更多 redis-memory-for-key 用法如下:

短引數 長引數 描述
-h –help 顯示幫助資訊
-s HOST –server=HOST Redis 伺服器地址
-p PORT –port=PORT Redis 伺服器埠號
-a PASSWORD –password PASSWORD Redis 伺服器密碼
-d DB –db DB 資料庫編號

上面介紹的是直接使用 rdb 命令進行的分析,也可以先生成報告檔案,然後作為原始資料匯入資料庫,做一些視覺化的處理工作。

總結

透過 rdbtools 工具可以對 rdb 檔案進行解析並生成分析報告,報告中包含了:key 名稱、型別、大小等關鍵資訊,透過這些資料進行不同維度的分析,可以解決各種 key 分佈的問題。

本作品採用《CC 協議》,轉載必須註明作者和本文連結
你應該瞭解真相,真相會讓你自由。

相關文章