高并發內存占用持續下降_師兄,為什么刪除數據后,Redis內存占用依然很高?...

前言

上周剛來了個應屆小師弟,組長說讓我帶著,周二問了我這樣一個問題:師兄啊,我用top命令看了下服務器的內存占用情況,發現Redis內存占用嚴重,于是我就刪除了大部分不用的keys,為什么內存占用還是很嚴重,并沒有釋放呢?

嗯?為什么呢?今天就帶著這個問題來介紹一下如何正確釋放Redis的內存。

什么是內存碎片?

內存碎片這個概念應該不是第一聽說了,熟悉JVM或者操作系統的應該都熟悉,以火車賣票為例,一個車廂128個車位,由于高峰期,只剩余兩個位置了,但是此時三個人想要坐在一起,能夠吹吹牛批,喝喝酒的,那么這三個人肯定不會買這節車廂的兩個位置了,此時這兩個位置可以稱之為座位碎片 。

操作系統中對于內存分配也是一樣的,比如應用需要申請一塊連續N個字節的空間,雖然剩余內存總量大于N個字節,但是沒有一塊連續的內存空間是N個字節,那么剩余的空間就是內存碎片。如下圖:

6a08c5d6244460b37181538ff4adb5bb.png

上圖中的空閑3個字節和空閑2個字節都是內存碎片。

那么什么原因會造成內存碎片呢?這個其實大致分為兩個原因,一個是操作系統的內存分配策略,一個是Redis自身原因,下面就這兩個原因詳細分析。

內存分配器的分配策略

內存分配器的分配策略一般是按照固定大小來分配內存,而不是按照應用程序申請的內存空間按需分配。比如8字節、16字節、32字節......

Redis提供了多種的內存分配策略,比如libcjemalloctcmalloc,默認使用jemalloc

jemalloc這種分配策略,是按照固定的空間分配,比如8字節、32字節....2KB、4KB等。當應用程序申請的內存接近某個固定值的時候,jemalloc則會分配固定的大小。比如申請了6字節,則會分配8字節的空間。

這種分配的方式的好處很明顯,則會減少內存分配的次數,比如申請了20字節的內存,實際分配的是32字節的內存空間,當應用再寫入10字節的數據時,則不會再次分配,剩余的12字節足夠用了。這樣就避免了一次的內存分配。如下圖:

1c0e46fb418007d3e387a6f5b0955419.png

但是壞處也很明顯,申請的和分配的空間不一樣,則剩余的空間很可能形成內存碎片,一旦內存碎片多了,內存利用率也會隨之降低,這是很可怕的。

Redis自身的原因

Redis作為鍵值對存儲的數據庫,本身鍵值對的大小就是不確定的,正如上面的例子中,Redis申請了20字節的空間,但實際分配卻是32字節,那么剩余的12字節則會被閑置成為內存碎片。如下圖:

bf382c2dfe88f05584168645b4cda100.png

上圖中剩余12個字節空間則是閑置的,很有可能成為內存碎片,因此鍵值對大小不同則會造成一定的內存碎片,這是第一個原因。

第二個原因其實理解起來很簡單,鍵值對的修改或者刪除肯定會造成空間的擴容或者釋放;

一方面,如果修改后的鍵值對變大或者變小了,勢必會將占用的空間擴大或者釋放不用的空間,如下圖:

6344602f873f08a6a2c510da7f2131a8.png

上圖中鍵值對修改后變小了,從原來的10個字節變成了7個字節,從而釋放了3個字節,此時剩余了5個字節的空閑空間。

另一方面,如果鍵值對刪除了,則會釋放掉占用的空間,形成空閑空間。

如何判斷存在內存碎片?

這個對于運維人員來說很重要,一旦出現Redis運行緩慢或者阻塞了,一定需要先判斷內存的占用情況,而不是說胡亂的重啟Redis。

Redis自身提供了INFO命令,可以用來查詢內存的使用情況,命令如下:


INFO?memory
#?Memory
used_memory:1073741736
used_memory_human:1024.00M
used_memory_rss:1997159792
used_memory_rss_human:1.86G

mem_fragmentation_ratio:1.86

上面的各種屬性含義如下:

823c7674b6c8a2193fdf2bb9c3958f3c.png

mem_fragmentation_ratio這個指標很清楚的展示了當前內存的碎片率,比如Redis申請了1000字節,但是操作系統實際分配的內存1800個字節,則mem_fragmentation_ratio=1800/1000=1.8

從上文也知道了,由于內存分配器的局限性,實際分配的內存絕大部分都是大于實際申請的內存,則如何通過mem_fragmentation_ratio這個值來衡量呢?這個值的范圍在多少是正常的呢?

作者這里參照了許多開發人員的建議,列出了以下經驗閥值:

  1. >1&&<1.5:在這個范圍內是合理的,畢竟大部分情況下操作系統分配的內存總是總是大于實際申請的空間。
  2. >1.5:這表明內存碎片率已經超過50%,此時需要采取一些措施來降低碎片率了。
  3. <1:what?表明實際分配的內存小于申請的內存了,很顯然內存不足了,這樣會導致部分數據寫入到Swap中,之后Redis訪問Swap中的數據時,延遲會變大,性能會降低。

如何清理內存碎片?

既然存在內存碎片,那么的一定有方法清除內存碎片,最簡單的方法則是重啟Redis

但是這也存在一些風險,如下;

  1. 如果Redis未持久化,則數據會丟失(忽略從后端恢復)
  2. 即使持久化了,但是恢復數據時長不定,這個要根據AOF和RDB文件大小決定,在恢復階段則無法提供服務。

好在Redis 4.0-RC3版本之后,Redis自身提供了一種清除內存碎片的方法

清除的原理很簡單,通過復制拷貝將不連續的存放的數據搬到一起形成一塊連續的內存空間,如下圖:

f3d050a11e31b23345f0219e5e4cfeeb.png

如上圖,清除之前AB不是連續的,中間隔著兩個字節空閑1,但是在執行清除內存碎片操作之后,Redis拷貝了B空閑1,釋放掉之前B的空間,此時空閑1空閑2則變成了連續的空閑空間了。

那么問題來了,這種方式固然好,但是對于單線程的Redis來說,通過這種拷貝復制的方式顯然是一種耗時的操作,性能大大降低,那么有什么好的方法呢?

Redis提供了參數配置,可以控制清除內存碎片的時機,命令如下:

config?set?activedefrag?yes

以上命令啟動自動清理,但是具體什么時候清理,還要受以下兩個參數的影響:

  1. active-defrag-ignore-bytes 400mb:如果內存碎片達到了400mb,開始清理(自定義)
  2. active-defrag-threshold-lower 20:內存碎片空間占操作系統分配給 Redis 的總空間比例達到20%時,開始清理(自定義)

以上兩個參數只有全部滿足才會開始清理

除了以上觸發清理內存碎片的參數,Redis還提供了兩個參數來保證在清理過程中不影響處理正常的請求,如下:

  1. active-defrag-cycle-min 25:表示自動清理過程所用 CPU 時間的比例不低于 25%,保證清理能正常開展
  2. active-defrag-cycle-max 75:表示自動清理過程所用 CPU 時間的比例不高于 75%,一旦超過,就停止清理,從而避免在清理時,大量的內存拷貝阻塞 Redis,導致響應延遲升高。

以上兩個參數控制了清理過程中的CPU時間占比,保證了正常處理請求不受影響

總結

本文以師弟的一個疑問開頭介紹了刪除數據導致內存占用還是很高的原因是存在內存碎片,導致內存碎片大致分為兩個原因,如下:

  1. 內存分配策略局限性,一般都會分配固定的空間大小,導致實際分配的內存空間大于實際申請的,從而多出了許多不連續的空閑內存塊。
  2. 鍵值對的修改、刪除導致了內存的擴容或者釋放,導致多余的不連續的空閑內存塊。

介紹了如何通過INFO memory命令查看內存的碎片率,通過mem_fragmentation_ratio的經驗閥值來判斷異常。

介紹了Redis清理內存碎片的方式以、自動清理的兩個觸發條件、保證正常處理請求的兩個控制CPU時間的參數。

另外,作者已經完成了兩個專欄的文章Mybatis進階、Spring Boot 進階 ,已經將專欄文章整理成書,有需要的公眾號回復關鍵詞Mybatis 進階Spring Boot 進階免費獲取。

c7971a3ce367789debda4d6ea42c2745.png
fde134451c082771570f945f67bd5e72.png

往期推薦

給你一個億的keys,Redis如何統計?

《Spring Boot 進階》肝了五萬多字的專欄文章,整理成冊,免費獲取!!!

程序員需知的 58 個網站

宕機了,Redis數據丟了怎么辦?

單線程的Redis有哪些 "慢" 動作?

頭禿系列,二十三張圖帶你從源碼分析Spring Boot 啟動流程~

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/542925.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/542925.shtml
英文地址,請注明出處:http://en.pswp.cn/news/542925.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何打印出給定尺寸的方格_打印給定號碼的表格| 8085微處理器

如何打印出給定尺寸的方格Problem statement: 問題陳述&#xff1a; Write an assembly language program in 8085 to print the table of input integer. 在8085中編寫匯編語言程序以打印輸入整數表。 Assumptions: Suppose the inputted number is at memory location 2050…

maka如何看html文件,自己在MAKA上做得H5,別人如何能看到收集的信息

1。登陸1。 ? ?登陸入口&#xff1a;點擊首頁右上角“登錄”按鈕進入登錄界面&#xff1b;2。 ? ?登陸界面&#xff1a;輸入有效注冊的個人賬號信息&#xff1a;郵箱、密碼&#xff1b;您也可以選擇QQ等第三方登錄。3。 ? ?密碼找回&#xff1a;進入賬戶登錄界面&#xf…

發現保存GIF格式后相素發生變化咋辦

數學公式編輯器MathType主要的作用就是編輯公式用的&#xff0c;一些用戶朋友編輯完公式希望把公式保存為“高分辨率”的GIF格式&#xff0c;但是在圖片查看器中進行瀏覽查看時發現GIF的分辨率發生了變化&#xff0c;對于這種情況該如何處理呢&#xff1f;下面我們就針對這個問…

3個階段 項目征名_2020年即將上線的3個爆款,或許它們能改變現有的手游格局...

在近幾年國內的手游市場中&#xff0c;基本都被《王者榮耀》和吃雞類型的給壟斷了&#xff0c;偶爾有個別爆款出現&#xff0c;也只是曇花一現&#xff0c;連半年時間都堅持不到&#xff0c;就比如去年的自走棋。不過在2020年&#xff0c;以王者和吃雞為主的這種格局或許會被打…

python判斷素數程序_使用面向對象方法檢查素數的Python程序

python判斷素數程序This program will check whether a given number is Prime or Not, in this program we will divide the number from 2 to square root of that number, if the number is divided by any number in b/w then the number will not be a prime number. 該程…

湖北計算機技能高考專科學校排名,湖北2021年技能高考專科錄取分數線

https://forms.ebdan.net/ls/wg2YPHOQ點擊查看全部院校武漢船舶職業技術學院&#xff1a;技能高考(機械類)507技能高考(電氣電子類)437技能高考(計算機類)532技能高考(財經類)530技能高考(建筑設計類)319技能高考(旅游類)489技能高考(汽車維修類)466湖北科技職業學院&#xff1…

定位樣式

Web頁面中的特殊效果&#xff0c;如菜單效果&#xff0c;對話框效果都需要通過定位屬性來實現。定位樣式position屬性可以控制元素的定位類型position屬性值可以為sataic、fixed、absolute、relativeposition屬性的語法結構- position:value;定位屬性static默認值。沒有定位&am…

c#異常處理_C#異常處理能力問題和解答 套裝2

c#異常處理1) There are the following statements that are given below, which is correct about an exception in C#.NET? The exception occurs at the time of compilationThe exception occurs during program loadingThe exception occurs during JIT compilationThe …

考慮題4所示的日志記錄_[南開大學]18秋學期(1703)《數據庫基礎與應用》在線作業...

18秋學期(1703)《數據庫基礎與應用》在線作業一、單選題&#xff1a;1.[單選題]在SQL語言中&#xff0c;模式對應于() (滿分:)A. 視圖和部分基本表B. 基本表C. 存儲文件D. 物理磁盤正確答案:——B——2.[單選題]在數據庫系統中&#xff0c;讀臟數據是指一個事務讀了另…

數字圖像處理圖像反轉的實現_反轉8位數字| 8085微處理器

數字圖像處理圖像反轉的實現Problem statement: 問題陳述&#xff1a; To reverse 8 bits number using 8085 microprocessors. 使用8085微處理器反轉8位數字。 Algorithm: 算法&#xff1a; Load the accumulator with the first data. 向累加器加載第一個數據。 Use RLC i…

計算機控制z反變換公式,第三章 計算機控制系統的數學描述(修正Z變換).ppt

第三章 計算機控制系統的數學描述(修正Z變換)* 3.4 修改Z變換 1&#xff0e;具有多采樣頻率系統 在某些控制系統中&#xff0c;存在著不同采樣頻率的采樣開關&#xff0c;如圖3.10所示。 圖3.10 具有不同采樣頻率系統結構圖 圖3.10表示&#xff0c;該系統反饋回路的采樣頻率高一…

7月19日實習日志

今天是實習第十二天&#xff0c;時間過得很快一轉眼實習一般都已經過去了&#xff0c;今天早上下了大雨&#xff0c;到單位的時候差一點遲到。 今天難道單位公司的同事就帶領著我給公司的防火請升級&#xff0c;防火墻可以是一套硬件或軟件&#xff0c;它在網絡和互聯網之間形成…

g++默認參數_C ++默認參數| 查找輸出程序| 套裝2

g默認參數Program 1: 程序1&#xff1a; #include <iostream>using namespace std;int K 10;int fun(){return K;}int sum(int X, int Y fun()){return (X Y);}int main(){int A 0;A sum(5);cout << A << " ";K 20;A sum(5);cout <<…

python重載模塊_Python 3.0中重載模塊

在Python中&#xff0c;每一個以 .py結尾的Python文件都是一個模塊。其他的文件可以通過導入一個模塊來讀取該模塊的內容。導入從本質上來講&#xff0c;就是載入另一個文件&#xff0c;并能夠讀取那個文件的內容。一個模塊的內容通過這樣的屬性能夠被外部世界使用。這種基于模…

計算機考研985院校不歧視,考研最不歧視的985大學有哪些

考研最不歧視的大學有很多&#xff0c;其中985院校有哈爾濱工業大學、對外經濟貿易大學、中南大學、河南大學和華東師范大學等。哪些985大學不歧視考研考生1、哈爾濱工業大學面試除了自我介紹&#xff0c;其他都不透露自己的信息&#xff0c;面試老師也都不知道&#xff0c;都是…

如何使用Tornado實現WebSocket服務器?

什么是龍卷風&#xff1f; (What is Tornado?) Tornado is a python web framework and asynchronous networking library. It is scalable and non-blocking. It specializes in dealing with event-driven networking. As tornado supports concurrent connections, natural…

電子增穩云臺_揭秘Dobby自拍無人機,電子增穩是黑科技?

揭秘Dobby自拍無人機&#xff0c;電子增穩是黑科技&#xff1f;2016年07月27日 10:47作者&#xff1a;廣州分站文章出處&#xff1a;泡泡網原創分享最近零度智控的Dobby自拍無人機橫空出世&#xff0c;主打「便攜」「自拍」兩大特色&#xff0c;一經眾籌便得到了大量的關注&…

拖動效果

css部分&#xff1a; <style type"text/css">.page{text-align:left;}.dragDiv{   border:1px solid #ddd;   padding:10px;   width:300px;   height:150px;   margin:0 auto;   border-radius:4px;    box-shadow:0 1px 2px #fefefe;    pos…

計算機組成比作人的什么位置,理學第章計算機組成上.ppt

理學第章計算機組成上.ppt第2章 計算機組成原理 2.1 計算機系統組成簡介 計算機系統由硬件和軟件兩大部分組成。若把一個計算機系統比作人的話&#xff0c;則硬件構成了計算機系統進行計算的軀干&#xff0c;軟件構成了計算機系統進行計算的大腦。 1 輸入部件 輸入部件用于向計…

Python | Tkinter中的文本區域和按鈕

Library: 圖書館&#xff1a; TkinterTkinter (Tkinter) Tkinter(Tk interface) is a Standard python library that is used to create easy, fast, and simple GUI applications. Tkinter(Tk接口)是一個標準的python庫&#xff0c;用于創建簡單&#xff0c;快速和簡單的GUI應…