Redis內存爆炸增長?你需要知道這一套Redis內存分析方法

Redis內存爆炸增長?你需要知道這一套Redis內存分析方法

Redis

Redis介紹

Redis內存爆炸增長?你需要知道這一套Redis內存分析方法

NoSQL

Redis是當前比較熱門的NOSQL數據庫之一,和Memcache一樣,數據都是緩存在計算機內存中。完全開源免費,遵守BSD協議,是一個高性能的key-value數據庫。通過在內存中讀寫數據,大大提高了數據讀寫速度,可以說Redis是實現網站高併發不可或缺的一部分。

Redis內存佔用分佈

Redis內存爆炸增長?你需要知道這一套Redis內存分析方法

Redis內存佔用

Redis作為內存數據庫,在內存中存儲的內容主要是數據(鍵值對);除了數據以外,Redis的其他部分也會佔用內存,內存佔用主要可以劃分為以下幾個部分:

數據

數據是數據庫最主要的組成部分。Redis使用鍵值對存儲數據,其中包括五種類型:字符串、哈希、列表、集合、有序集合。

本身運行需要的內存

Redis本身也是一個程序,主進程運行及創建的子進程運行也需要佔用內存,但這部分佔用內存極少,大多數情況下可以忽略。

緩衝內存

緩衝內存包括客戶端緩衝區、複製積壓緩衝區、AOF緩衝區等,這部分佔用內存也很少。

內存碎片

內存碎片是Redis在分配、回收物理內存過程中產生的。內存碎片產生原因主要是對數據的頻繁修改造成,導致Redis釋放的空間在物理內存中並沒有被釋放。若Redis服務器中內存碎片很大,可以通過安全重啟方式釋放內存。

Redis內存分析過程

Redis內存爆炸增長?你需要知道這一套Redis內存分析方法

內存分析

分析Redis內存我們一般會採用bgsave生成dump.rdb文件再結合redis-rdb-tools和 sqlite或其他數據庫來進行靜態分析。

BGSAVE:在後臺異步(Asynchronously)保存當前數據庫的數據到磁盤。

BGSAVE 命令執行之後立即返回 OK,然後 Redis fork 出一個新子進程,原來的 Redis 進程(父進程)繼續處理客戶端請求,而子進程則負責將數據保存到磁盤,然後退出。

生成內存快照:redis-rdb-tools 是一個 python 的解析 rdb 文件的工具,在分析內存的時候,主要用它生成內存快照。

安裝redis-rdb-tools

1.使用pip安裝

# pip install rdbtools

2.使用源碼安裝

# 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 和其他值。

$head memory.csv
database,type,key,size_in_bytes,encoding,num_elements,len_largest_element
0,string,coupon.id:652601465,112,string,8,8
0,string,coupon.id:631354838,112,string,8,8
0,string,coupon.id:632477800,112,string,8,8
0,string,coupon.id:620902294,112,string,8,8
0,string,coupon.id:631432959,112,string,8,8
0,string,coupon.id:632933399,112,string,8,8
0,string,coupon.id:632117725,112,string,8,8
0,string,coupon.id:634240609,112,string,8,8
0,string,coupon.id:646312603,112,string,8,8

使用SQLite分析內存快照

SQLite版本必須是3.16.0以上。

導入之前生成的csv文件:

$sqlite3 memory.db
SQLite version 3.19.3 2017-06-27 16:48:08
Enter ".help" for usage hints.
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

數據導入後,可以使用sql來查詢我們所需的內容。

示例:

查詢內容佔用最高的幾個key:

sqlite> select key,size_in_bytes from memory order by size_in_bytes desc limit 10;
key,size_in_bytes
xx.xx:xx,7860169636
xx.xx:xx,3043206524
xx.xx:xx,1866022916
xx.xx:xx,420931316
xx.xx:xx,171118172
xx.xx:xx,162984940
xx.xx:xx,133443892
xx.xx:xx,80925132
xx.xx:xx,28340356

查詢出佔用內容較高的key,做相應策略即可,快速止血方案可以刪掉這些key來釋放內存,長期來看,此類key設計必然不合理,業務層可能也會有問題,需要與研發一起制定方案。

後記

Redis內存爆炸增長?你需要知道這一套Redis內存分析方法

計算機中的數據

Redis使用起來很簡單,但是用好卻不容易。工作中作者至少遇到了兩次因為Redis key設計不合理而導致Redis內存爆炸式增長的事故。查找出設計不合理的key並處理掉雖然可以解決問題,但是卻是治標不治本,想要從根本解決,還得有一套Redis使用規範,當然這套規範就不在本文的討論範圍內了。


分享到:


相關文章: