欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis內(nèi)存碎片率調(diào)優(yōu)處理方式

 更新時間:2024年09月30日 10:22:18   作者:小馬運維的一天  
Redis集群因內(nèi)存碎片率超過1.5觸發(fā)告警,分析發(fā)現(xiàn)內(nèi)因與外因?qū)е聝?nèi)存碎片,內(nèi)因為操作系統(tǒng)內(nèi)存分配機制,外因為Redis操作特性,使用Redis內(nèi)置內(nèi)存碎片清理機制可有效降低碎片率,但需注意可能影響性能,建議使用MEMORY命令診斷內(nèi)存使用情況,合理配置參數(shù)以優(yōu)化性能

1.背景概述

在生產(chǎn)環(huán)境中Redis Cluster集群觸發(fā)了內(nèi)存碎片化的告警(碎片率>1.5),集群節(jié)點分布三臺宿主機六個節(jié)點三主三從架構(gòu),Redis版本是6.2.X。

2.redis內(nèi)存碎片的形成

內(nèi)存碎片形成的原因主要有2點:

  • 內(nèi)因:操作系統(tǒng)的內(nèi)存分配機制。
  • 外因:Redis的負載特征造成。

內(nèi)因:

內(nèi)存分配器會按照固定大小來分配內(nèi)存,而不是按需分配。例如Linux下默認是4KB,開啟內(nèi)存大頁機制后就變成2MB。

Redis中使用jemalloc分配器來分配內(nèi)存。它會按照一系列固定大小的內(nèi)存來進行分配。例如當Redis中需要申請一個20B大小的空間來保存數(shù)據(jù),那么jemalloc分配器就會分配32B:

倘若此時應用還要寫入5B大小的數(shù)據(jù),那么無需申請額外的空間。

倘若此時應用還要寫入20B大小的數(shù)據(jù),那么必須在申請額外的空間了,此時就會有產(chǎn)生內(nèi)存碎片的風險(之前分配的32B中,10B就是內(nèi)存碎片了)

外因:

我們有一個Redis實例,里面有著不同大小的鍵值對,那么根據(jù)內(nèi)存分配器的分配機制來看。就有可能分配著不同大小的連續(xù)內(nèi)存空間。

另一方面,我們對鍵值對也有可能有著不同的操作,增刪改查。

如圖所示

上圖中,白色部分的就是內(nèi)存碎片,可以看出大小不一的鍵值對以及修改刪除操作導致產(chǎn)生了內(nèi)存碎片。

3.清理內(nèi)存碎片

清理內(nèi)存碎片之前,首先應該做的就是判斷是否有內(nèi)存碎片:

我們可以登錄Redis后使用INFO MEMORY命令查看。mem_fragmentation_ratio參數(shù)的值就是內(nèi)存碎片化的值。

mem_fragmentation_ratio代表Redis實例當前的內(nèi)存碎片率。其計算公式為:

mem_fragmentation_ratio = used_memory_rss / used_memory

  • used_memory_rss:操作系統(tǒng)實際分配Redis的物理內(nèi)存空間。
  • used_memory:Redis為了保存數(shù)據(jù)而實際申請的空間。

針對mem_fragmentation_ratio,有兩個參考:

  • mem_fragmentation_ratio ∈ (1, 1.5]:屬于合理范圍內(nèi),暫時可以放放。
  • mem_fragmentation_ratio ∈ (1.5, +∞):表明內(nèi)存碎片率超過了50%,需要采取措施降低內(nèi)存碎片率。

那么如何清理內(nèi)存碎片呢(一般不會重啟實例,因為生產(chǎn)上往往不允許這種神操作出現(xiàn)),在Redis4.0版本以后,Redis提供了內(nèi)置的內(nèi)存碎片清理機制。

#內(nèi)存碎片回收機制使用
activedefrag yes
# active-defrag-ignore-bytes與active-defrag-threshold-lower兩個條件同時滿足會觸發(fā)內(nèi)存碎片清理,當有一個不滿足則停止清理
# 啟動活動碎片整理的最小碎片浪費量,內(nèi)存碎片的字節(jié)數(shù)達到100M時開始清理
active-defrag-ignore-bytes 100mb
# 啟動活動碎片整理的最小碎片百分比,內(nèi)存碎片空間占操作系統(tǒng)分配給redis的總空間比例達到 10% 時開始清理
active-defrag-threshold-lower 10
# 內(nèi)存碎片超過 100%,則盡最大努力整理
active-defrag-threshold-upper 100
# 以CPU百分比表示的碎片整理的最小工作量,自動清理過程所用CPU時間的比例不低于5%,保證能正常清理
active-defrag-cycle-min 5
# 自動清理過程所用CPU時間的比例不高于75%,超過75%停止清理,避免redis主線程阻塞
active-defrag-cycle-max 75

以上參數(shù)可根據(jù)主機資源配置及應用場景自行調(diào)整。

除此之外,值得注意的是,雖然Redis提供了這樣的自動內(nèi)存清理機制,能夠帶來清理內(nèi)存碎片的好處,但是與此同時的必定有著其對應的犧牲,也就是性能影響問題。

Redis提供了內(nèi)置的內(nèi)存碎片清理機制的使用前提是在編譯的過程中添加了內(nèi)存分配器參數(shù)MALLOC=jemalloc

make MALLOC=jemalloc

4.擴展

當然我們在生產(chǎn)環(huán)境使用Redis過程中也可以使用自帶的命令進行內(nèi)存使用情況的診斷,便于我們及時對問題進行優(yōu)化處理。

我們可以使用MEMORY help查看:

127.0.0.1:6379> MEMORY help
1) MEMORY <subcommand> arg arg ... arg. Subcommands are:
2) DOCTOR - Return memory problems reports.
3) MALLOC-STATS -- Return internal statistics report from the memory allocator.
4) PURGE -- Attempt to purge dirty pages for reclamation by the allocator.
5) STATS -- Return information about the memory usage of the server.
6) USAGE <key> [SAMPLES <count>] -- Return memory in bytes used by <key> and its value. Nested values are sampled up to <count> times (default: 5).

MEMORY STATS

redis的內(nèi)存使用不只包含全部的key-value數(shù)據(jù),還有描述這些key-value的元信息,以及許多管理功能的消耗,好比持久化、主從復制,經(jīng)過MEMORY STATS能夠更好的了解到redis的內(nèi)存使用情況

127.0.0.1:6379> MEMORY STATS
 1) "peak.allocated"
 2) (integer) 13749176
 3) "total.allocated"
 4) (integer) 7308872
 5) "startup.allocated"
 6) (integer) 791424
 7) "replication.backlog"
 8) (integer) 0
 9) "clients.slaves"
10) (integer) 0
11) "clients.normal"
12) (integer) 2587994
13) "aof.buffer"
14) (integer) 0
15) "lua.caches"
16) (integer) 1912
17) "db.0"
18) 1) "overhead.hashtable.main"
    2) (integer) 285216
    3) "overhead.hashtable.expires"
    4) (integer) 1568
19) "overhead.total"
20) (integer) 3668114
21) "keys.count"
22) (integer) 5492
23) "keys.bytes-per-key"
24) (integer) 1186
25) "dataset.bytes"
26) (integer) 3640758
27) "dataset.percentage"
28) "55.861713409423828"
29) "peak.percentage"
30) "53.158615112304688"
31) "allocator.allocated"
32) (integer) 7323560
33) "allocator.active"
34) (integer) 8429568
35) "allocator.resident"
36) (integer) 12427264
37) "allocator-fragmentation.ratio"
38) "1.1510205268859863"
39) "allocator-fragmentation.bytes"
40) (integer) 1106008
41) "allocator-rss.ratio"
42) "1.4742468595504761"
43) "allocator-rss.bytes"
44) (integer) 3997696
45) "rss-overhead.ratio"
46) "0.65557020902633667"
47) "rss-overhead.bytes"
48) (integer) -4280320
49) "fragmentation"
50) "1.1209555864334106"
51) "fragmentation.bytes"
52) (integer) 879088

一共有15項內(nèi)容,內(nèi)存使用量均以字節(jié)為單位

1. peak.allocated

redis啟動到如今,最多使用過多少內(nèi)存。

2. total.allocated

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

3. startup.allocated

redis啟動初始化時使用的內(nèi)存,有不少讀者會比較奇怪,為何個人redis啟動之后什么都沒作就已經(jīng)占用了幾十MB的內(nèi)存?

這是由于redis自己不只存儲key-value,還有其余的內(nèi)存消耗,好比共享變量、主從復制、持久化和db元信息,下面各項會有詳細介紹。

4. replication.backlog

主從復制backlog使用的內(nèi)存,默認10MB,backlog只在主從斷線重連時發(fā)揮做用,主從復制自己并不依賴此項。

5. clients.slaves

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

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

那么主從之間就不免會有數(shù)據(jù)的延遲,若是主從之間鏈接斷開,重連時為了保證數(shù)據(jù)的一致性就要作一次全量同步,這顯然是不夠高效的。

backlog就是為此而設計,master在backlog中緩存一部分主從復制的增量數(shù)據(jù),斷線重連時若是slave的偏移量在backlog中,那就能夠只把偏移量以后的增量數(shù)據(jù)同步給slave便可,避免了全量同步的開銷。

6. clients.normal

除slave外全部其余客戶端的讀寫緩沖區(qū)。

有時候一些客戶端讀取不及時,就會形成output-buffer積壓占用內(nèi)存過多的狀況,能夠經(jīng)過配置項client-output-buffer-limit來限制,當超過閾值以后redis就會主動斷開鏈接以釋放內(nèi)存,slave亦是如此。

7. aof.buffer

此項為aof持久化使用的緩存和aofrewrite時產(chǎn)生的緩存之和,固然若是關(guān)閉了appendonly那這項就一直為0:less

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

aofrewrite時緩存增量數(shù)據(jù)使用的內(nèi)存,只在aofrewrite時才會使用。

能夠看出這一項的大小與寫入流量成正比。ide

8. db.0

redis每一個db的元信息使用的內(nèi)存,這里只使用了db0,因此只打印了db0的內(nèi)存使用狀態(tài),當使用其余db時也會有相應的信息。優(yōu)化

db的元信息有如下三項:

  • a) redis的db就是一張hash表,首先就是這張hash表使用的內(nèi)存(redis使用鏈式hash,hash表中存放全部鏈表的頭指針);
  • b) 每個key-value對都有一個dictEntry來記錄他們的關(guān)系,元信息便包含該db中全部dictEntry使用的內(nèi)存;
  • c) redis使用redisObject來描述value所對應的不一樣數(shù)據(jù)類型(string、list、hash、set、zset),那么redisObject占用的空間也計算在元信息中。

overhead.hashtable.main:

db的元信息也便是以上三項之和,計算公式為:

hashtable + dictEntry + redisObject

overhead.hashtable.expires:

對于key的過時時間,redis并無把它和value放在一塊兒,而是單獨用一個hashtable來存儲,可是expires這張hash表記錄的是key-expire信息,因此不須要`redisObject`來描述value,其元信息也就少了一項,計算公式為:

hashtable + dictEntry

9. overhead.total

3-8項之和:startup.allocated+replication.backlog+clients.slaves+clients.normal+aof.buffer+dbx

10. dataset.bytes

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

11. dataset.percentage

全部數(shù)據(jù)占比,這里并無直接使用total.allocated作分母,而是除去了redis啟動初始化的內(nèi)存,計算公式為:

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

12. keys.count

redis當前存儲的key總量

13. keys.bytes-per-key

平均每一個key的內(nèi)存大小,直覺上應該是用dataset.bytes除以keys.count便可,可是redis并無這么作,而是把管理類內(nèi)存也平攤到了每一個key的內(nèi)存使用中,計算公式為:

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

14. peak.percentage

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

15. fragmentation

內(nèi)存碎片率

MEMORY USAGE

使用方法:MEMORY USAGE <key> [SAMPLES <count>]

命令參數(shù)很少,經(jīng)過字面意思也能夠看出來是評估指定key的內(nèi)存使用狀況。samples是可選參數(shù)默認為5,以hash為例看下:

127.0.0.1:6379> HGETALL 9527
1) "name"
2) "zhouxingxing"
3) "age"
4) "50"
5) "city"
6) "hongkong"
127.0.0.1:6379> MEMORY USAGE 9527
(integer) 101

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

與overhead.hashtable.main不一樣的是,每一個dictEntry中key-value都是字符串,因此沒redisObject的額外消耗。

在評估真正的數(shù)據(jù)內(nèi)存大小時redis并無去遍歷全部key,而是采用的抽樣估算:隨機抽取samples個key-value對計算其平均內(nèi)存占用,再乘以key-value對的個數(shù)即獲得結(jié)果。

試想一下若是要精確計算內(nèi)存占用,那么就須要遍歷全部的元素,當元素不少時就是使redis阻塞,因此請合理設置samples的大小。

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

MEMORY DOCTOR

此項子命令是做者給出的關(guān)于redis內(nèi)存使用方面的建議,在不一樣的容許狀態(tài)下會有不一樣的分析結(jié)果。

首先是沒問題的狀況

運行狀態(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ù)量很小,暫無建議:

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.

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

Sam, I detected a few issues in this Redis instance memory implants:

* 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.

I'm here to keep you safe, Sam. I want to help you.

內(nèi)存碎片率太高超過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.
每一個slave緩沖區(qū)的平均內(nèi)存超過10MB,緣由多是master寫入流量太高,也有多是主從同步的網(wǎng)絡帶寬不足或者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)存超過200KB,緣由多是pipeline使用不當或者Pub/Sub客戶端處理消息不及時致使:

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.

MEMORY MALLOC-STATS

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

MEMORY PURGE

請求分配器釋放內(nèi)存,只對jemalloc生效。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Redis鎖的過期時間小于業(yè)務的執(zhí)行時間如何續(xù)期

    Redis鎖的過期時間小于業(yè)務的執(zhí)行時間如何續(xù)期

    本文主要介紹了Redis鎖的過期時間小于業(yè)務的執(zhí)行時間如何續(xù)期,Redisson它能給Redis分布式鎖實現(xiàn)過期時間自動續(xù)期,具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • redis哈希和集合_動力節(jié)點Java學院整理

    redis哈希和集合_動力節(jié)點Java學院整理

    這篇文章主要為大家詳細介紹了redis哈希和集合的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-08-08
  • ?Redis?實現(xiàn)計數(shù)器和限速器的示例代碼

    ?Redis?實現(xiàn)計數(shù)器和限速器的示例代碼

    本文主要介紹了?Redis?實現(xiàn)計數(shù)器和限速器的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-02-02
  • Redis Cluster的圖文講解

    Redis Cluster的圖文講解

    今天小編就為大家分享一篇關(guān)于Redis Cluster的圖文講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • Centos7安裝redis的超詳細步驟教程

    Centos7安裝redis的超詳細步驟教程

    Redis是當前比較熱門的NOSQL系統(tǒng)之一,它是一個key-value存儲系統(tǒng),下面這篇文章主要介紹了Centos7安裝redis的超詳細步驟,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2024-10-10
  • Redis 命令整理并說明如何使用

    Redis 命令整理并說明如何使用

    這篇文章主要介紹了Redis 命令整理并說明如何使用的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • Redis使用Bitmap的方法實現(xiàn)

    Redis使用Bitmap的方法實現(xiàn)

    本文主要介紹了Redis使用Bitmap的方法實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-01-01
  • Redis主從復制的實現(xiàn)示例

    Redis主從復制的實現(xiàn)示例

    Redis主從復制實現(xiàn)多機備份,本文就來介紹一下Redis主從復制的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-11-11
  • Redis實現(xiàn)Session持久化的示例代碼

    Redis實現(xiàn)Session持久化的示例代碼

    Redis是內(nèi)存數(shù)據(jù)庫,數(shù)據(jù)都是存儲在內(nèi)存中,為了避免服務器斷電等原因?qū)е翿edis進程異常退出后數(shù)據(jù)的永久丟失,本文主要介紹了Redis實現(xiàn)Session持久化的示例代碼,感興趣的可以了解一下
    2023-09-09
  • Redis安裝使用RedisJSON模塊的方法

    Redis安裝使用RedisJSON模塊的方法

    在使用Redis中,我們可以使用大量的Redis模塊來擴展Redis的功能,本文主要介紹了Redis安裝使用RedisJSON模塊的方法,具有一定的參考價值,感興趣的可以了解一下
    2022-03-03

最新評論