背景
線上經常遇到用戶想知道自己 Redis 實例中數據的內存分布情況。為了不影響線上實例的使用,我們一般會采用 bgsave 生成 dump.rdb 文件,再結合 redis-rdb-tools 和 sqlite 來進行靜態分析。總的來說,整個分析的過程簡單而實用,是每一個 Redis 的用戶都非常值得掌握的一個方法。
創建備份
自建 Redis 可在客戶端執行 bgsave
生成 rdb 文件。雲數據庫 Redis 版可以在控制台上可以進行數據備份和下載的操作,下載后的數據為 rdb 格式文件。步驟詳見下圖:
生成內存快照
redis-rdb-tools 是一個 python 的解析 rdb 文件的工具,主要有以下三個功能:
- 生成內存快照
- 轉儲成 json 格式
- 使用標准的 diff 工具比較兩個 dump 文件
在分析內存的使后,我們主要用到它的生成內存快照功能。
redis-rdb-tools 安裝
redis-rdb-tools 有兩種安裝方式,任選其一即可。
使用 PYPI 安裝
pip install rdbtools
從源碼安裝
git clone https://github.com/sripathikrishnan/redis-rdb-tools
cd redis-rdb-tools
sudo python setup.py install
使用 redis-rdb-tools 生成內存快照
生成內存快照的命令為:
rdb -c memory dump.rdb > memory.csv
生成 CSV 格式的內存報告。包含的列有:數據庫 ID,數據類型,key,內存使用量(byte),編碼。內存使用量包含 key、value 和其他值。
注意:內存使用量是理論上的近似值,在一般情況下,略低於實際值。memory.csv 例子:
$head memory.csv
database,type,key,size_in_bytes,encoding,num_elements,len_largest_element
0,string,"orderAt:377671748",96,string,8,8
0,string,"orderAt:413052773",96,string,8,8
0,sortedset,"Artical:Comments:7386",81740,skiplist,479,41
0,sortedset,"pay:id:18029",2443,ziplist,84,16
0,string,"orderAt:452389458",96,string,8,8
分析內存快照
SQLite 是一款輕型的數據庫。我們可以將前面生成的 csv 導入到數據庫中之后,就可以利用 sql 語句很方便的對 Redis 的內存數據進行各種分析了。
導入方法
sqlite3 memory.db
sqlite> create table memory(database int,type varchar(128),key varchar(128),size_in_bytes int,encoding varchar(128),num_elements int,len_largest_element varchar(128));
sqlite>.mode csv memory
sqlite>.import memory.csv memory
數據導入以后,接下來想怎么分析就怎么分析了,舉幾個簡單的例子:
查詢key個數
sqlite>select count(*) from memory;
查詢總的內存占用
sqlite>select sum(size_in_bytes) from memory;
查詢內存占用最高的10個 key
sqlite>select * from memory order by size_in_bytes desc limit 10;
查詢成員個數1000個以上的 list
sqlite>select * from memory where type='list' and num_elements > 1000 ;
總結
通過使用 redis-rdb-tools + sqlite 的方式,可以方便的對 redis 實例的內存情況進行靜態的分析。整個過程也比較簡單,獲取到 rdb 之后即可。
rdb -c memory dump.rdb > memory.csv;
sqlite3 memory.db
sqlite> create table memory(database int,type varchar(128),key varchar(128),size_in_bytes int,encoding varchar(128),num_elements int,len_largest_element varchar(128));
sqlite>.mode csv memory
sqlite>.import memory.csv memory
實際使用中,發現過一個 List 積攢了10多 GB 的內容,也發現過43 MB 以上的 string 類型的 value, 往往不僅能解答用戶的疑惑,而且能夠幫助用戶排除業務中潛在的風險點,找到業務性能瓶頸。
(轉自阿里雲)