基於Python項目的Redis緩存消耗內存數據簡單分析(附詳細操作步驟)


目錄

1 准備工作

2 具體實施

 

 


1 准備工作

什么是Redis?

Redis:一個高性能的key-value數據庫。支持數據的持久化,可以將內存中的數據保存在磁盤中,重啟的時候可以再次加載進行使用;提供string、list、set、zset、hash等數據結構的存儲,並支持數據的備份。

 

本文適合使用的場景:當一個項目中Redis緩存的數據量逐漸增大,Redis緩存的數據占用內存也會越來越大,而且其中有很多很可能是價值不大的數據。由於Redis是一個key-value數據庫,所以對其中的數據進行分析沒有mysql數據庫那么直觀。那么此時,我們需要尋找工具來分析Redis緩存中的哪些數據占用內存比較大,並結合項目實際的情況來分析這些數據存儲的價值如何?從而作出具體刪減數據的方案,來解放服務器端寶貴的內存資源。

 

本文需要采用的工具:Rdbtools和MySQL。

Rdbtools:使用Python語言編寫的,可以解析Redis的dump.rdb文件。此外,提供以下工具:

(1)跨所有數據庫和密鑰生成數據的內存報告

(2)將dump文件轉換為JSON

(3)使用標准diff工具比較兩個dump文件

具體源碼GitHub鏈接:https://github.com/sripathikrishnan/redis-rdb-tools/

 

MySQL:一種開源且比較輕量級的關系型數據庫。本文使用Rdbtools解析出Redis的dump.rdb文件並生成內存報告*.csv文件(PS:下文操作文件為result_facelive_hot.csv),然后把該文件導入到MySQL數據庫中,最后通過編寫具體的SQL語句腳本生成想要的數據分析結果的*.csv文件(PS:下文SQL腳本中生成的文件名為redis_key_storage.csv)。

 

 


2 具體實施

Rdbtools工具在以下操作,需要Python2.7或者Python3.6等版本環境的支持。

(1)找到本機項目使用Redis生成的dump.rdb文件具體所在地址。(PS:本文操作的項目是一個基於Django框架,部署在Ubuntu系統上,所以相關命令都是該系統下的實際操作,其它環境基本類似,就不作介紹)

sudo find / -name '*.rdb'

運行上述命令后,即可看到本機上所有以.rdb為后綴文件的所有具體地址,然后根據項目實際情況,找到具體地址。例如,本文找到的地址:

/home/facelive/redis/data/hot/dump.rdb  

PS:有的項目,使用Redis時,會把默認的dump.rdb文件進行了重新命名,例如命名為db-dump.rdb文件。那么此時如何判定具體命名呢?

可以查看項目使用Redis數據庫的redis.conf文件內容,並結合以下命令:

cat -n redis.conf |grep "dbfilename"

即可查看具體的文件名。

(2)使用Rdbtools生成項目中使用Redis的內存使用的*.csv文件

此處需要項目先安裝Rdbtools工具,項目且是基於Python環境。激活項目的虛擬環境,輸入命令:

pip install rdbtools python-lzf

(3)安裝完成后,即可在項目的虛擬環境中使用rdb命令。此處本文生成內存報告的命令如下:

rdb -c memory /home/facelive/redis/data/hot/dump.rdb > ~/result_facelive_hot.csv   

生成的result_facelive_hot.csv文件會存放在服務器環境根目錄。此時,可以從服務器把生成的文件復制到本地,具體操作命令參考:

sudo scp facelive@188.100.10.10:/home/facelive/result_facelive_hot.csv .  # 從服務器復制遠程文件到本地當前所在根目錄,這里的ip是我自己隨便寫的噢

然后在本地打開result_facelive_hot.csv文件,結果如下(以下截圖結果是在Windows環境下打開的噢):

 

可以看到該表中有database(對應的數據庫)、type(緩存的類型)、key(緩存的key名稱)、size_in_bytes(該key具體占用內存大小,這是本文數據分析的核心數據)、encoding(緩存key的編碼)、num_elements和len_larget_element六列數據。

(4)把result_facelive_hot.csv導入到MySQL數據庫,進行數據分析

首先,選定本地MySQL數據庫中某一已經創建好的數據庫,並在該數據庫中創建一個名稱為redis_hot的表(PS:具體表名可隨意定)

創建表的SQL語句:

DROP TABLE IF EXISTS `redis_hot`;

CREATE TABLE `redis_hot` (

  `database` int(11) DEFAULT NULL,

  `type` varchar(100) DEFAULT NULL,

  `key` varchar(200) DEFAULT NULL,

  `size_in_bytes` int(11) DEFAULT NULL,

  `encoding` varchar(255) DEFAULT NULL,

  `num_elements` int(11) DEFAULT NULL,

  `len_largest_element` int(11) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

創建好redis_hot表后,我們開始使用Navicat工具來進行數據導入工作。

 

PS:此處也可以使用腳本來完成具體數據寫入,使用腳本命令的好處是,當導入的CSV文件過大,即數據量很大的時候,使用Navicat客戶端會假死,導致數據壓根就無法導入,但是腳本可以正常一鍵導入,不會出現問題。不過以下的使用Navaicat的方法還是可以參考一下。具體腳本代碼如下:

create database if not exists facelive_redis default character set 'utf8';

use facelive_redis;

DROP TABLE IF EXISTS `redis_hot`;
CREATE TABLE `redis_hot` (
  `database` int(11) DEFAULT NULL,
  `type` varchar(100) DEFAULT NULL,
  `key` varchar(200) DEFAULT NULL,
  `size_in_bytes` int(11) DEFAULT NULL,
  `encoding` varchar(255) DEFAULT NULL,
  `num_elements` int(11) DEFAULT NULL,
  `len_largest_element` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

load data local infile '~/facelive_redis/result_facelive_hot.csv'  # 此處修改為自己文件保存的具體實際地址即可
into table redis_hot character set gb2312
fields terminated by ',' optionally enclosed by '"' escaped by '"'
lines terminated by '\n';

 

以下操作是在Windows環境下進行,其它環境使用Navicat可視化工具,操作步驟基本類似。

首先,使用Navicat打開本地數據庫,找到剛剛創建的redis_hot表,鼠標點擊右鍵,選擇導入向導,具體流程如下:

 

 

 

 

 

 

 

 

 

 

 

 

 

數據導入完成后,下面正式開始編寫SQL查詢腳本,生成具體所需分析結果數據。

此處需要分析的數據:

(1)每一種key所在用的總內存大小(size_in_bytes_sum)

(2)每一種key的總數(PS:因為有的key設計是前綴+用戶id,這樣的情況都屬於一種key)(record_count)

(3)每一種key所在數據庫(database)

(4)每一種key的數據類型(type)

(5)每一種key的編碼類型(encoding)

(6)每一種key的名稱(key)

(7)每一種key占用的平均內存大小(size_in_bytes_avg)

 

使用的SQL腳本代碼如下:

# core_user
SELECT ANY_VALUE(`database`) as `database`, ANY_VALUE(type) as type, ANY_VALUE(`key`) as `key`, ANY_VALUE(encoding) as encoding, count(`database`) as record_count, SUM(size_in_bytes) as size_in_bytes_sum, AVG(size_in_bytes) as size_in_bytes_avg FROM redis_hot WHERE `key` LIKE 'user_verify_code_%'
UNION SELECT ANY_VALUE(`database`) as `database`, ANY_VALUE(type) as type, ANY_VALUE(`key`) as `key`, ANY_VALUE(encoding) as encoding, count(`database`) as record_count, SUM(size_in_bytes) as size_in_bytes_sum, AVG(size_in_bytes) as size_in_bytes_avg FROM redis_hot WHERE `key` LIKE 'robot_id_list%'
UNION ... # 此處是使用連接(UNION)查詢,每一個`SELECT`查詢代表一個`key`信息,所以后續項目中`key`跟新時,也需要在本文件中寫入一個新的連接查詢 ... # 指定的數據中查詢`key`不存在,則最后統一返回一條全是0的數據,相當於過濾作用

 

/* 此處可以繼續使用UNION來並查其他名稱的key具體分析數據,下面一行代碼是生成redis_key_storage.csv文件,如果注釋掉,就可以直接在Navicat查詢界面查看具體查詢結果 */ 

into outfile 'E:/redis_key_storage.csv' fields terminated by ','
optionally enclosed by '"' lines terminated by '\r\n';
# 其中可以修改具體文件保存地址(此處文件保存地址:
'E:/redis_key_storage.csv'

最終得到的結果數據如下:

 

好啦,介紹這里就結束了,希望能對觀看本文的同學有所幫助~

 

 


參考資料:

1.使用代碼完成csv文件導入Mysql(https://blog.csdn.net/quiet_girl/article/details/71436108)

2.使用rdbtools工具來解析redis dump.rdb文件及內存使用量(http://www.ywnds.com/?p=8441)

3.MySQL必知必會:組合查詢(Union)(https://segmentfault.com/a/1190000007926959)

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM