溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

redis4.0下MEMORY命令詳解

發(fā)布時(shí)間:2021-08-31 02:17:15 來(lái)源:億速云 閱讀:160 作者:chen 欄目:關(guān)系型數(shù)據(jù)庫(kù)

這篇文章主要介紹“redis4.0下MEMORY命令詳解”,在日常操作中,相信很多人在redis4.0下MEMORY命令詳解問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”redis4.0下MEMORY命令詳解”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

前言

在過(guò)去,查看redis的內(nèi)存使用狀態(tài)只有info memory命令,而且也只有一些基礎(chǔ)信息,想要獲取全局信息就有些困難。4.0開(kāi)始redis提供了MEMORY命令,一切都變得簡(jiǎn)單起來(lái)。

MEMORY命令

MEMORY命令一共有5個(gè)子命令,可以通過(guò)MEMORY HELP來(lái)查看:

127.0.0.1:6379> memory help

1) "MEMORY DOCTOR - Outputs memory problems report"

2) "MEMORY USAGE <key> [SAMPLES <count>] - Estimate memory usage of key"

3) "MEMORY STATS - Show memory usage details"

4) "MEMORY PURGE - Ask the allocator to release memory"

5) "MEMORY MALLOC-STATS - Show allocator internal stats"

接下來(lái)我們從MEMORY STATS開(kāi)始,一一介紹各個(gè)子命令的功能。

1. MEMORY STATS

首先,我們需要明確一個(gè)概念,redis的內(nèi)存使用不僅包含所有的key-value數(shù)據(jù),還有描述這些key-value的元信息,以及許多管理功能的消耗,比如持久化、主從復(fù)制,通過(guò)MEMORY STATS可以更好的了解到redis的內(nèi)存使用狀況。

這里我們啟動(dòng)了一個(gè)打開(kāi)持久化功能并且?guī)lave的redis,向其中隨機(jī)寫入了一些數(shù)據(jù)(某些數(shù)據(jù)還帶有過(guò)期時(shí)間),以便讀者可以更好的了解redis的內(nèi)存使用,接下來(lái)執(zhí)行MEMORY STATS命令:

127.0.0.1:6379> memory stats

 1) "peak.allocated"

 2) (integer) 423995952

 3) "total.allocated"

 4) (integer) 11130320

 5) "startup.allocated"

 6) (integer) 9942928

 7) "replication.backlog"

 8) (integer) 1048576

 9) "clients.slaves"

10) (integer) 16858

11) "clients.normal"

12) (integer) 49630

13) "aof.buffer"

14) (integer) 3253

15) "db.0"

16) 1) "overhead.hashtable.main"

    2) (integer) 5808

    3) "overhead.hashtable.expires"

    4) (integer) 104

17) "overhead.total"

18) (integer) 11063904

19) "keys.count"

20) (integer) 94

21) "keys.bytes-per-key"

22) (integer) 12631

23) "dataset.bytes"

24) (integer) 66416

25) "dataset.percentage"

26) "5.5934348106384277"

27) "peak.percentage"

28) "2.6251003742218018"

29) "fragmentation"

30) "1.1039986610412598"

一共有15項(xiàng)內(nèi)容,內(nèi)存使用量均以字節(jié)為單位,我們一個(gè)一個(gè)來(lái)看:

1. peak.allocated

redis啟動(dòng)到現(xiàn)在,最多使用過(guò)多少內(nèi)存。

2. total.allocated

當(dāng)前使用的內(nèi)存總量。

3. startup.allocated

redis啟動(dòng)初始化時(shí)使用的內(nèi)存,有很多讀者會(huì)比較奇怪,為什么我的redis啟動(dòng)以后什么都沒(méi)做就已經(jīng)占用了幾十MB的內(nèi)存?

這是因?yàn)閞edis本身不僅存儲(chǔ)key-value,還有其他的內(nèi)存消耗,比如共享變量、主從復(fù)制、持久化和db元信息,下面各項(xiàng)會(huì)有詳細(xì)介紹。

4. replication.backlog

主從復(fù)制backlog使用的內(nèi)存,默認(rèn)10MB,backlog只在主從斷線重連時(shí)發(fā)揮作用,主從復(fù)制本身并不依賴此項(xiàng)。

5. clients.slaves

主從復(fù)制中所有slave的讀寫緩沖區(qū),包括output-buffer(也即輸出緩沖區(qū))使用的內(nèi)存和querybuf(也即輸入緩沖區(qū)),這里簡(jiǎn)單介紹一下主從復(fù)制:

redis把一次事件循環(huán)中,所有對(duì)數(shù)據(jù)庫(kù)發(fā)生更改的內(nèi)容先追加到slave的output-buffer中,在事件循環(huán)結(jié)束后統(tǒng)一發(fā)送給slave。

那么主從之間就難免會(huì)有數(shù)據(jù)的延遲,如果主從之間連接斷開(kāi),重連時(shí)為了保證數(shù)據(jù)的一致性就要做一次全量同步,這顯然是不夠高效的。backlog就是為此而設(shè)計(jì),master在backlog中緩存一部分主從復(fù)制的增量數(shù)據(jù),斷線重連時(shí)如果slave的偏移量在backlog中,那就可以只把偏移量之后的增量數(shù)據(jù)同步給slave即可,避免了全量同步的開(kāi)銷。

6. clients.normal

除slave外所有其他客戶端的讀寫緩沖區(qū)。

有時(shí)候一些客戶端讀取不及時(shí),就會(huì)造成output-buffer積壓占用內(nèi)存過(guò)多的情況,可以通過(guò)配置項(xiàng)client-output-buffer-limit來(lái)限制,當(dāng)超過(guò)閾值之后redis就會(huì)主動(dòng)斷開(kāi)連接以釋放內(nèi)存,slave亦是如此。

7. aof.buffer

此項(xiàng)為aof持久化使用的緩存和aofrewrite時(shí)產(chǎn)生的緩存之和,當(dāng)然如果關(guān)閉了appendonly那這項(xiàng)就一直為0:

redis并不是在有寫入時(shí)就立即做持久化的,而是在一次事件循環(huán)內(nèi)把所有的寫入數(shù)據(jù)緩存起來(lái),待到事件循環(huán)結(jié)束后再持久化到磁盤。

aofrewrite時(shí)緩存增量數(shù)據(jù)使用的內(nèi)存,只在aofrewrite時(shí)才會(huì)使用,aofrewrite機(jī)制可以參考之前的文章《redis4.0之利用管道優(yōu)化aofrewrite》。

可以看出這一項(xiàng)的大小與寫入流量成正比。

8. db.0

redis每個(gè)db的元信息使用的內(nèi)存,這里只使用了db0,所以只打印了db0的內(nèi)存使用狀態(tài),當(dāng)使用其他db時(shí)也會(huì)有相應(yīng)的信息。

db的元信息有以下三項(xiàng):

a) redis的db就是一張hash表,首先就是這張hash表使用的內(nèi)存(redis使用鏈?zhǔn)絟ash,hash表中存放所有鏈表的頭指針);

b) 每一個(gè)key-value對(duì)都有一個(gè)dictEntry來(lái)記錄他們的關(guān)系,元信息便包含該db中所有dictEntry使用的內(nèi)存;

c) redis使用redisObject來(lái)描述value所對(duì)應(yīng)的不同數(shù)據(jù)類型(string、list、hash、set、zset),那么redisObject占用的空間也計(jì)算在元信息中。

overhead.hashtable.main:

db的元信息也即是以上三項(xiàng)之和,計(jì)算公式為:

hashtable + dictEntry + redisObject

overhead.hashtable.expires:

對(duì)于key的過(guò)期時(shí)間,redis并沒(méi)有把它和value放在一起,而是單獨(dú)用一個(gè)hashtable來(lái)存儲(chǔ),但是expires這張hash表記錄的是key-expire信息,所以不需要`redisObject`來(lái)描述value,其元信息也就少了一項(xiàng),計(jì)算公式為:

hashtable + dictEntry

9. overhead.total

3-8項(xiàng)之和:startup.allocated+replication.backlog+clients.slaves+clients.normal+aof.buffer+dbx

10. dataset.bytes

所有數(shù)據(jù)所使用的內(nèi)存——也即total.allocated - overhead.total——當(dāng)前內(nèi)存使用量減去管理類內(nèi)存使用量。

11. dataset.percentage

所有數(shù)據(jù)占比,這里并沒(méi)有直接使用total.allocated做分母,而是除去了redis啟動(dòng)初始化的內(nèi)存,計(jì)算公式為:

100 * dataset.bytes / (total.allocated - startup.allocated)

12. keys.count

redis當(dāng)前存儲(chǔ)的key總量

13. keys.bytes-per-key

平均每個(gè)key的內(nèi)存大小,直覺(jué)上應(yīng)該是用dataset.bytes除以keys.count即可,但是redis并沒(méi)有這么做,而是把管理類內(nèi)存也平攤到了每個(gè)key的內(nèi)存使用中,計(jì)算公式為:

(total.allocated - startup.allocated) / keys.count

14. peak.percentage

當(dāng)前使用內(nèi)存與歷史最高值比例

15. fragmentation

內(nèi)存碎片率

2. MEMORY USAGE

相信所有redis用戶都希望對(duì)每一個(gè)key-value的內(nèi)存使用了如指掌,然而4.0之前redis并沒(méi)有提供一個(gè)明確的方法來(lái)進(jìn)行內(nèi)存評(píng)估,不過(guò)從4.0開(kāi)始,MEMORY命令實(shí)現(xiàn)了這一功能。

首先看下使用方法:MEMORY usage [samples]

命令參數(shù)不多,通過(guò)字面意思也可以看出來(lái)是評(píng)估指定key的內(nèi)存使用情況。samples是可選參數(shù)默認(rèn)為5,以hash為例看下其如果工作:

首先類似于上一節(jié)中的overhead.hashtable.main,要計(jì)算hash的元信息內(nèi)存,包括hash表的大小以及所有dictEntry的內(nèi)存占用信息。

與overhead.hashtable.main不同的是,每個(gè)dictEntry中key-value都是字符串,所以沒(méi)redisObject的額外消耗。在評(píng)估真正的數(shù)據(jù)內(nèi)存大小時(shí)redis并沒(méi)有去遍歷所有key,而是采用的抽樣估算:隨機(jī)抽取samples個(gè)key-value對(duì)計(jì)算其平均內(nèi)存占用,再乘以key-value對(duì)的個(gè)數(shù)即得到結(jié)果。試想一下如果要精確計(jì)算內(nèi)存占用,那么就需要遍歷所有的元素,當(dāng)元素很多時(shí)就是使redis阻塞,所以請(qǐng)合理設(shè)置samples的大小。

其他數(shù)據(jù)結(jié)構(gòu)的計(jì)算方式類似于hash,此處就不再贅述。

3. MEMORY DOCTOR

此項(xiàng)子命令是作者給出的關(guān)于redis內(nèi)存使用方面的建議,在不同的允許狀態(tài)下會(huì)有不同的分析結(jié)果:

首先是沒(méi)問(wèn)題的情況

運(yùn)行狀態(tài)良好:

Hi Sam, I can't find any memory issue in your instance. I can only account for what occurs on this base.

redis的數(shù)據(jù)量很小,暫無(wú)建議:

Hi Sam, this instance is empty or is using very little memory, my issues detector can't be used in these conditions. Please, leave for your mission on Earth and fill it with some data. The new Sam and I will be back to our programming as soon as I finished rebooting.

接下來(lái)出現(xiàn)的結(jié)果就需要注意了

內(nèi)存使用峰值1.5倍于目前內(nèi)存使用量,此時(shí)內(nèi)存碎片率可能會(huì)比較高,需要注意:

Peak memory: In the past this instance used more than 150% the memory that is currently using. The allocator is normally not able to release memory after a peak, so you can expect to see a big fragmentation ratio, however this is actually harmless and is only due to the memory peak, and if the Redis instance Resident Set Size (RSS) is currently bigger than expected, the memory will be used as soon as you fill the Redis instance with more data. If the memory peak was only occasional and you want to try to reclaim memory, please try the MEMORY PURGE command, otherwise the only other option is to shutdown and restart the instance.

內(nèi)存碎片率過(guò)高超過(guò)1.4,需要注意:

High fragmentation: This instance has a memory fragmentation greater than 1.4 (this means that the Resident Set Size of the Redis process is much larger than the sum of the logical allocations Redis performed). This problem is usually due either to a large peak memory (check if there is a peak memory entry above in the report) or may result from a workload that causes the allocator to fragment memory a lot. If the problem is a large peak memory, then there is no issue. Otherwise, make sure you are using the Jemalloc allocator and not the default libc malloc.

每個(gè)slave緩沖區(qū)的平均內(nèi)存超過(guò)10MB,原因可能是master寫入流量過(guò)高,也有可能是主從同步的網(wǎng)絡(luò)帶寬不足或者slave處理較慢:

Big slave buffers: The slave output buffers in this instance are greater than 10MB for each slave (on average). This likely means that there is some slave instance that is struggling receiving data, either because it is too slow or because of networking issues. As a result, data piles on the master output buffers. Please try to identify what slave is not receiving data correctly and why. You can use the INFO output in order to check the slaves delays and the CLIENT LIST command to check the output buffers of each slave.

普通客戶端緩沖區(qū)的平均內(nèi)存超過(guò)200KB,原因可能是pipeline使用不當(dāng)或者Pub/Sub客戶端處理消息不及時(shí)導(dǎo)致:

Big client buffers: The clients output buffers in this instance are greater than 200K per client (on average). This may result from different causes, like Pub/Sub clients subscribed to channels bot not receiving data fast enough, so that data piles on the Redis instance output buffer, or clients sending commands with large replies or very large sequences of commands in the same pipeline. Please use the CLIENT LIST command in order to investigate the issue if it causes problems in your instance, or to understand better why certain clients are using a big amount of memory.

4. MEMORY MALLOC-STATS

打印內(nèi)存分配器狀態(tài),只在使用jemalloc時(shí)有用。

5. MEMORY PURGE

請(qǐng)求分配器釋放內(nèi)存,同樣只對(duì)jemalloc生效。

到此,關(guān)于“redis4.0下MEMORY命令詳解”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注億速云網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI