Redis內存空間簡單分析

背景

最近發現項目中用的 redis 內存消耗很大(但是印象中卻以為沒有這么多的key的內存消耗才對呀?),使用 info 命令可以看到所有key占用的一些內存大小以及key的數量等等,如下圖所示(只截圖了memory和keyspace部分):

可以發現, info 命令只能看到總的內存大小以及key的數量等。這些對于分析到底哪些或哪類key占用的內存較大是遠遠不夠的!

工具調研

工欲善其事必先利其器!

在各種google搜索之后,發現有一個工具貌似是可以的: redis-rdb-tools

于是分頭行動,

讓運維將線上rdb快照文件用scp拷貝到一臺測試機上(畢竟在線上機器上操作是不太安全的)

我需要用最快最干凈的方式來安裝一下rdb工具,這里選擇直接在python docker中裝。

分析之路

根據該工具? , 可以將 rdb 快照文件轉換為 csv 格式文件:

拿到csv文件后有兩種做法,

直接用python pandas 庫分塊讀取csv文件,可以做一些統計、過濾等操作(幾乎有與等價于sql的api操作方式

將csv導入到關系型數據庫,用sql來操作,比較靈活 。關于數據庫選型:在試驗過mysql和postgres兩款關系型數據庫后,感觸挺深, mysql單表導入完上面csv中大概3億多條數據后,查詢直接癱瘓!postgres導入數據后依然堅挺(平均一條like 查詢十幾秒左右,還是可以接受的!)。

just try!

rdb 文件轉換為csv

(這里因為是操作的內部的業務數據,有些數據細節不便公開,僅貼出相關重要命令以及一些踩坑后的經驗方法等)

# 1. 先運行一個python docker容器(注意將rdb文件掛載進去)docker run? -it -v YOUR_PATH/xxx.rdb:/data/xxx.rdb? python bash

# 2. 安裝rdb toolspip install rdbtools python-lzf

# 3. 執行rdb 轉為csv命令 (此過程根據rdb文件大小時間不定)rdb -c memory /data/xxx.rdb? -f memory.csv

上述命令中有些路徑和名稱注意替換為你自己真實的值。

csv 簡單清洗

話說這里也是個坑來著,在往 postgres 數據庫導入csv數據時,報了一個大概意思是 “實際的列個數和期待的列個數不匹配”錯誤。 可能rdb tools在轉換的時候某些行的值有點問題,或者其他bug導致。 這里鑒于有異常的數據條數不多,不用太過于深究,直接用 pandas 簡單清洗一下即可。

相關python代碼如下:

import pandas as pd

import numpy as np

reader = pd.read_csv('/xxxx/memory.csv', iterator=True,error_bad_lines=False)

loop = True

chunkSize =10000000

chunks=[]

total_bytes=0

while loop:

? ? try:

? ? ? ? chunk = reader.get_chunk(chunkSize)

? ? ? ? chunks.append(chunk)

? ? except StopIteration:

? ? ? ? loop = False

? ? ? ? print("Iteration is stopped.")

df = pd.concat(chunks, ignore_index=True)

df.to_csv('/xxx/memory2.csv', sep=',', encoding='utf-8')

大概解釋下,這里先讀取csv文件,指定選項 error_bad_lines=False ,則pandas會自動忽略有問題的行。接著用分塊的方式讀完所有內容,最后合并然后寫到新文件。

csv導入postgres

此步驟其實理論上非必須的,上文說到其實可以直接用 pandas 操作csv幾乎可以完成跟sql類似的分析效果。 但比較還是直接用sql比較方便,還是導到數據庫來的實惠。

# 1. 運行postgres docker容器(記得把上面步驟中轉換得到的csv文件掛載進去)

docker run --name postgres -v /xxx/memory2.csv:/memory.csv? -d postgres:9.6

# 2. 進入postgres容器內部 psql shell

docker exec -it postgres psql -U postgres

# 3. 創建臨時表 (建議是所有字段是用text,否則導入可能會遇到轉型錯誤,第一個字段index是pandas帶進來的,可以導出csv時處理下)

postgres=# create table keys_dump(

index integer,

database text,

type text,

key text,

size_in_bytes text,

encoding text,

num_elements text,

len_largest_element text,

expiry text

);

# 4. 執行導入csv文件命令

postgres=# COPY keys_dump FROM '/memory.csv' WITH csv;

sql分析

現在問題會比較簡單了,這里因為key中涉及到一些實際業務值,下面只是簡單列舉一下比如統計 string 類型的key占用的總內存大小:

select sum(size_in_bytes::int) from keys_dump where type='text';

諸如此類的sql,根據你的實際場景,比如按key中某關鍵詞進行like查詢:

select sum(size_in_bytes::int) from keys_dump where type='text' and key like 'xxxx%';

或者來個統計單key大小前10條:

select *? from keys_dump order by size_in_bytes::int desc limit 10;

以上sql語句,我自己都試過,在單表3億多的行數中執行,總時間大概10幾到二十幾秒左右,整體速度還是讓人能接受的,畢竟只是做下離線分析。

歡迎工作一到五年的Java工程師朋友們加入Java架構開發: 855835163

群內提供免費的Java架構學習資料(里面有高可用、高并發、高性能及分布式、Jvm性能調優、Spring源碼,MyBatis,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點的架構資料)合理利用自己每一分每一秒的時間來學習提升自己,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕,使勁拼,給未來的自己一個交代!

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • pyspark.sql模塊 模塊上下文 Spark SQL和DataFrames的重要類: pyspark.sql...
    mpro閱讀 9,487評論 0 13
  • Redis 內存分析方法 背景 線上經常遇到用戶想知道自己 Redis 實例中數據的內存分布情況。為了不影響線上實...
    Jack0111閱讀 1,412評論 1 3
  • 剛上初中時遇到一位語文老師,眼睛里有光的短發女老師,第一次知道有種作文叫主題作文。一種不用固定標題,在一個主題里天...
    薄情的世界深情地活著閱讀 4,261評論 3 6
  • 引子 張先,北宋著名詞人,自詡“三影郎中”,一生富足長壽,詩酒風流,工書,善畫,精詞,著有《張子野詞》,存詞180...
    劍行天下閱讀 2,902評論 9 13
  • 文/Nico -01- 大概八年前吧,有一個關系不錯的高中女同學。 仍然記得見她最后一面的時候,她高昂著頭,說著寬...
    Nico尼可閱讀 855評論 3 20