標籤:

Redis 應該如何節約使用內存?有什麼好的設計策略和好的方法?


Redis內存分析方法-博客-雲棲社區-阿里雲

背景

線上經常遇到用戶想知道自己Redis實例中數據的內存分布情況。
為了不影響線上實例的使用,我們一般會採用bgsave生成dump.rdb文件,再結合redis-rdb-tools和sqlite來進行靜態分析。

創建備份

自建Redis可在客戶端執行bgsave生成rdb文件。
阿里雲資料庫Redis版可以在控制台上可以進行數據備份和下載的操作,下載後的數據為rdb格式文件。
步驟詳見下圖:

生成內存快照

redis-rdb-tools是一個python的解析rdb文件工具, 主要有一下三個功能:
1. 生成內存快照
2. 轉儲成json格式
3. 使用標準的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多G的內容,也發現過43M以上的string類型的value, 往往不僅能解答用戶的疑惑,而且能夠幫助用戶排除業務中潛在的風險點,找到業務性能瓶頸。

總的來說,整個分析的過程簡單而實用,是每一個Redis的用戶都非常值得掌握的一個方法。


要節約內存,首先需要了解Redis的內存用到哪去了。比如最基礎的,key值不要太長,或者像instagram的案例中一樣,用hash結構將多個key合併成一個key,以利用hash結構的小數據量壓縮功能。節約內存的方法真的很多,但都需要根據自己的應用場景來做決策。

instagram的案例可以看這裡:http://blog.nosqlfan.com/html/3379.html


把真正需要用到redis的數據存進去。根據數據請求的冷熱不同定期清理或轉移到mysql。


利用一些簡單的可逆的演算法進行分庫存儲,例如按照用戶ID,在一定範圍的用戶ID存儲到指定的Redis庫中,這樣既能有效擴展,就不用擔心內存不夠用了。

當然如果涉及到不同庫中數據的不停交換,對性能的影響也需要考慮到


盡量使用hset,hget

盡量避免使用set、list等數據結構

設置redis的最大內存不超過物理內存,提前做好容量規劃


推薦閱讀:

NoSQL如何快速入門?
矽谷之路5:NoSQL就是把東西放在一起
時間序列數據的存儲和計算 - 開源時序資料庫解析(一)
MongoDB 存儲引擎 mmapv1 原理解析
對於 Web 2.0 實時應用、大數據量,MongoDB 和 memcached + SQL 哪個性能更好、在國內比較容易僱工程師?

TAG:Redis | NoSQL |