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 哪個性能更好、在國內比較容易僱工程師?