內(nèi)存分析能提取業(yè)務(wù)特點(diǎn),了解業(yè)務(wù)瓶頸,發(fā)現(xiàn)業(yè)務(wù)Bug。比如一些用戶說他們的Key并不多,但是內(nèi)存卻已滿,分析后才發(fā)現(xiàn),一個(gè)List有16G,相當(dāng)于把售賣的數(shù)據(jù)都放到了同一個(gè)Key里面。業(yè)務(wù)量不多的時(shí)候沒問題,業(yè)務(wù)量增加的時(shí)候,Key就已經(jīng)很大了,說明當(dāng)前的代碼已經(jīng)遠(yuǎn)遠(yuǎn)跟不上業(yè)務(wù)的發(fā)展。
內(nèi)存分析方法有兩種,一種在線,一種離線。一般采用離線方法,離線內(nèi)存分析是把Redis的數(shù)據(jù)存下來,放到本地,不會(huì)有風(fēng)險(xiǎn),數(shù)據(jù)可以任意操作,主要分為3步:一是生成rdb文件(bgsave),二是生成內(nèi)存快照,三是分析內(nèi)存快照。每一步都很簡單,生成內(nèi)存快照會(huì)用到一個(gè)開源的工具,Redis-rdb-tools,用來做rdb文件的分析。命令為db -c memory dump.rdb > memory.csv。生成的內(nèi)存快照為csv格式,包含:
Database:數(shù)據(jù)庫ID
?Type:數(shù)據(jù)類型
?Key:
?size_in_bytes:理論內(nèi)存值(比實(shí)際略低)
?Encoding:編碼方式
?num_elements:成員個(gè)數(shù)
?len_largest_element:最大成員長度
其中每一個(gè)Key都有六列數(shù)據(jù),表明屬于第幾號數(shù)據(jù)庫,這里要注意理論內(nèi)存值,會(huì)比實(shí)際略低。程序員可以將生成后的快照導(dǎo)入到數(shù)據(jù)庫,可以用sqlite,然后進(jìn)行數(shù)據(jù)分析,這里簡單列舉幾條。
查詢Key個(gè)數(shù):sqlite> select count(*) from memory;
?查詢總的內(nèi)存占用:sqlite> select sum(size_in_bytes) from memory;
?查詢內(nèi)存占用最高的10個(gè)Key:sqlite> select * from memory order by size_in_bytes desc limit 10;
?查詢成員個(gè)數(shù)1000個(gè)以上的list:sqlite> select * from memory where type='list' and num_elements > 1000 ;
接下來是在線內(nèi)存分析,這里以簡單的Redis-cli為例,有一個(gè)-bigKeys的選項(xiàng),可以把每種類型Key的最大Key找出來。
在這里再分享兩個(gè)其他的內(nèi)存分析問題。有時(shí)候Redis產(chǎn)品可能并沒有多少東西,內(nèi)存卻滿了,從而排查出來是其他方面的內(nèi)存占用。一個(gè)可能是client占用內(nèi)存的關(guān)系,因?yàn)橛胷db分析的時(shí)候沒有client,線上的很多連接都會(huì)帶著一個(gè)很長的命令,Redis里面就會(huì)有緩存,dict rehash也會(huì)占用一些內(nèi)存。內(nèi)存分析時(shí)發(fā)現(xiàn)有一些哈希表的內(nèi)存占據(jù)特別大,因?yàn)橛行㎏ey很少被訪問,導(dǎo)致rehash被很少觸發(fā),中間緩存的表會(huì)一直刪不掉。這里可以用一個(gè)腳本訪問觸發(fā)rehash,看內(nèi)存是否變化,把表刪掉即可。
原地址:https://mp.weixin.qq.com/s/n4HXKXPKf87qgZ_e6s4gPg