<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          萬(wàn)字總結(jié),Redis 性能問(wèn)題排查解決手冊(cè)!

          共 10719字,需瀏覽 22分鐘

           ·

          2021-05-29 04:37

          公眾號(hào)關(guān)注杰哥的IT之旅”,

          選擇“星標(biāo)”,重磅干貨,第一時(shí)間送達(dá)!

          性能相關(guān)的數(shù)據(jù)指標(biāo)

          通過(guò)Redis-cli命令行界面訪問(wèn)到Redis服務(wù)器,然后使用info命令獲取所有與Redis服務(wù)相關(guān)的信息。通過(guò)這些信息來(lái)分析文章后面提到的一些性能指標(biāo)。

          info命令輸出的數(shù)據(jù)可分為10個(gè)類(lèi)別,分別是:

          1、server
          2、clients
          3、memory
          4、persistence
          5、stats
          6、replication
          7、cpu
          8、commandstats
          9、cluster
          10、keyspace

          這篇主要介紹比較重要的2部分性能指標(biāo)memory和stats。

          需要注意的是info命令返回的信息,并沒(méi)有命令響應(yīng)延遲相關(guān)的數(shù)據(jù)信息,所以后面會(huì)詳細(xì)介紹怎么獲取與延遲相關(guān)的數(shù)據(jù)指標(biāo)。

          倘若你覺(jué)得info輸出的信息太多并且雜亂無(wú)章,可以指定info命令的參數(shù)來(lái)獲取單個(gè)分類(lèi)下的數(shù)據(jù)。比如輸入info memory命令,會(huì)只返回與內(nèi)存相關(guān)的數(shù)據(jù)。

          為了快速定位并解決性能問(wèn)題,這里選擇5個(gè)關(guān)鍵性的數(shù)據(jù)指標(biāo),它包含了大多數(shù)人在使用Redis上會(huì)經(jīng)常碰到的性能問(wèn)題。

          內(nèi)存使用率used_memory

          上圖中used_memory 字段數(shù)據(jù)表示的是:由Redis分配器分配的內(nèi)存總量,以字節(jié)(byte)為單位。其中used_memory_human上的數(shù)據(jù)和used_memory是一樣的值,它以M為單位顯示,僅為了方便閱讀。

          used_memory是Redis使用的內(nèi)存總量,它包含了實(shí)際緩存占用的內(nèi)存和Redis自身運(yùn)行所占用的內(nèi)存(如元數(shù)據(jù)、lua)。它是由Redis使用內(nèi)存分配器分配的內(nèi)存,所以這個(gè)數(shù)據(jù)并沒(méi)有把內(nèi)存碎片浪費(fèi)掉的內(nèi)存給統(tǒng)計(jì)進(jìn)去。

          其他字段代表的含義,都以字節(jié)為單位:

          1、used_memory_rss:從操作系統(tǒng)上顯示已經(jīng)分配的內(nèi)存總量。
          2、mem_fragmentation_ratio:內(nèi)存碎片率。
          3、used_memory_lua:Lua腳本引擎所使用的內(nèi)存大小。

          mem_allocator:在編譯時(shí)指定的Redis使用的內(nèi)存分配器,可以是libc、jemalloc、tcmalloc。

          因內(nèi)存交換引起的性能問(wèn)題

          內(nèi)存使用率是Redis服務(wù)最關(guān)鍵的一部分。如果一個(gè)Redis實(shí)例的內(nèi)存使用率超過(guò)可用最大內(nèi)存 (used_memory > 可用最大內(nèi)存),那么操作系統(tǒng)開(kāi)始進(jìn)行內(nèi)存與swap空間交換,把內(nèi)存中舊的或不再使用的內(nèi)容寫(xiě)入硬盤(pán)上(硬盤(pán)上的這塊空間叫Swap分區(qū)),以便騰出新的物理內(nèi)存給新頁(yè)或活動(dòng)頁(yè)(page)使用。
          在硬盤(pán)上進(jìn)行讀寫(xiě)操作要比在內(nèi)存上進(jìn)行讀寫(xiě)操作,時(shí)間上慢了近5個(gè)數(shù)量級(jí),內(nèi)存是0.1μs單位、而硬盤(pán)是10ms。如果Redis進(jìn)程上發(fā)生內(nèi)存交換,那么Redis和依賴(lài)Redis上數(shù)據(jù)的應(yīng)用會(huì)受到嚴(yán)重的性能影響。通過(guò)查看used_memory指標(biāo)可知道Redis正在使用的內(nèi)存情況,如果used_memory>可用最大內(nèi)存,那就說(shuō)明Redis實(shí)例正在進(jìn)行內(nèi)存交換或者已經(jīng)內(nèi)存交換完畢。管理員根據(jù)這個(gè)情況,執(zhí)行相對(duì)應(yīng)的應(yīng)急措施。

          跟蹤內(nèi)存使用率

          若是在使用Redis期間沒(méi)有開(kāi)啟rdb快照或aof持久化策略,那么緩存數(shù)據(jù)在Redis崩潰時(shí)就有丟失的危險(xiǎn)。因?yàn)楫?dāng)Redis內(nèi)存使用率超過(guò)可用內(nèi)存的95%時(shí),部分?jǐn)?shù)據(jù)開(kāi)始在內(nèi)存與swap空間來(lái)回交換,這時(shí)就可能有丟失數(shù)據(jù)的危險(xiǎn)。

          當(dāng)開(kāi)啟并觸發(fā)快照功能時(shí),Redis會(huì)fork一個(gè)子進(jìn)程把當(dāng)前內(nèi)存中的數(shù)據(jù)完全復(fù)制一份寫(xiě)入到硬盤(pán)上。因此若是當(dāng)前使用內(nèi)存超過(guò)可用內(nèi)存的45%時(shí)觸發(fā)快照功能,那么此時(shí)進(jìn)行的內(nèi)存交換會(huì)變的非常危險(xiǎn)(可能會(huì)丟失數(shù)據(jù))。倘若在這個(gè)時(shí)候?qū)嵗嫌写罅款l繁的更新操作,問(wèn)題會(huì)變得更加嚴(yán)重。

          通過(guò)減少Redis的內(nèi)存占用率,來(lái)避免這樣的問(wèn)題,或者使用下面的技巧來(lái)避免內(nèi)存交換發(fā)生:

          1、假如緩存數(shù)據(jù)小于4GB,就使用32位的Redis實(shí)例。因?yàn)?2位實(shí)例上的指針大小只有64位的一半,它的內(nèi)存空間占用空間會(huì)更少些。這有一個(gè)壞處就是,假設(shè)物理內(nèi)存超過(guò)4GB,那么32位實(shí)例能使用的內(nèi)存仍然會(huì)被限制在4GB以下。要是實(shí)例同時(shí)也共享給其他一些應(yīng)用使用的話,那可能需要更高效的64位Redis實(shí)例,這種情況下切換到32位是不可取的。不管使用哪種方式,Redis的dump文件在32位和64位之間是互相兼容的, 因此倘若有減少占用內(nèi)存空間的需求,可以嘗試先使用32位,后面再切換到64位上。

          2、盡可能的使用Hash數(shù)據(jù)結(jié)構(gòu)。因?yàn)镽edis在儲(chǔ)存小于100個(gè)字段的Hash結(jié)構(gòu)上,其存儲(chǔ)效率是非常高的。所以在不需要集合(set)操作或list的push/pop操作的時(shí)候,盡可能的使用Hash結(jié)構(gòu)。比如,在一個(gè)web應(yīng)用程序中,需要存儲(chǔ)一個(gè)對(duì)象表示用戶(hù)信息,使用單個(gè)key表示一個(gè)用戶(hù),其每個(gè)屬性存儲(chǔ)在Hash的字段里,這樣要比給每個(gè)屬性單獨(dú)設(shè)置一個(gè)key-value要高效的多。通常情況下倘若有數(shù)據(jù)使用string結(jié)構(gòu),用多個(gè)key存儲(chǔ)時(shí),那么應(yīng)該轉(zhuǎn)換成單key多字段的Hash結(jié)構(gòu)。如上述例子中介紹的Hash結(jié)構(gòu)應(yīng)包含,單個(gè)對(duì)象的屬性或者單個(gè)用戶(hù)各種各樣的資料。Hash結(jié)構(gòu)的操作命令是HSET(key, fields, value)和HGET(key, field),使用它可以存儲(chǔ)或從Hash中取出指定的字段。

          3、設(shè)置key的過(guò)期時(shí)間。一個(gè)減少內(nèi)存使用率的簡(jiǎn)單方法就是,每當(dāng)存儲(chǔ)對(duì)象時(shí)確保設(shè)置key的過(guò)期時(shí)間。倘若key在明確的時(shí)間周期內(nèi)使用或者舊key不大可能被使用時(shí),就可以用Redis過(guò)期時(shí)間命令(expire,expireat, pexpire, pexpireat)去設(shè)置過(guò)期時(shí)間,這樣Redis會(huì)在key過(guò)期時(shí)自動(dòng)刪除key。假如你知道每秒鐘有多少個(gè)新key-value被創(chuàng)建,那可以調(diào)整key的存活時(shí)間,并指定閥值去限制Redis使用的最大內(nèi)存。

          4、回收key。在Redis配置文件中(一般叫Redis.conf),通過(guò)設(shè)置“maxmemory”屬性的值可以限制Redis最大使用的內(nèi)存,修改后重啟實(shí)例生效。也可以使用客戶(hù)端命令config set maxmemory 去修改值,這個(gè)命令是立即生效的,但會(huì)在重啟后會(huì)失效,需要使用config rewrite命令去刷新配置文件。若是啟用了Redis快照功能,應(yīng)該設(shè)置“maxmemory”值為系統(tǒng)可使用內(nèi)存的45%,因?yàn)榭煺諘r(shí)需要一倍的內(nèi)存來(lái)復(fù)制整個(gè)數(shù)據(jù)集,也就是說(shuō)如果當(dāng)前已使用45%,在快照期間會(huì)變成95%(45%+45%+5%),其中5%是預(yù)留給其他的開(kāi)銷(xiāo)。如果沒(méi)開(kāi)啟快照功能,maxmemory最高能設(shè)置為系統(tǒng)可用內(nèi)存的95%。

          當(dāng)內(nèi)存使用達(dá)到設(shè)置的最大閥值時(shí),需要選擇一種key的回收策略,可在Redis.conf配置文件中修改“maxmemory-policy”屬性值。若是Redis數(shù)據(jù)集中的key都設(shè)置了過(guò)期時(shí)間,那么“volatile-ttl”策略是比較好的選擇。但如果key在達(dá)到最大內(nèi)存限制時(shí)沒(méi)能夠迅速過(guò)期,或者根本沒(méi)有設(shè)置過(guò)期時(shí)間。那么設(shè)置為“allkeys-lru”值比較合適,它允許Redis從整個(gè)數(shù)據(jù)集中挑選最近最少使用的key進(jìn)行刪除(LRU淘汰算法)。Redis還提供了一些其他淘汰策略,如下:

          1、volatile-lru:使用LRU算法從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集合中淘汰數(shù)據(jù)。
          2、volatile-ttl:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集合中挑選即將過(guò)期的數(shù)據(jù)淘汰。
          3、volatile-random:從已設(shè)置過(guò)期時(shí)間的數(shù)據(jù)集合中隨機(jī)挑選數(shù)據(jù)淘汰。
          4、allkeys-lru:使用LRU算法從所有數(shù)據(jù)集合中淘汰數(shù)據(jù)。
          5、allkeys-random:從數(shù)據(jù)集合中任意選擇數(shù)據(jù)淘汰
          6、no-enviction:禁止淘汰數(shù)據(jù)。

          通過(guò)設(shè)置maxmemory為系統(tǒng)可用內(nèi)存的45%或95%(取決于持久化策略)和設(shè)置“maxmemory-policy”為“volatile-ttl”或“allkeys-lru”(取決于過(guò)期設(shè)置),可以比較準(zhǔn)確的限制Redis最大內(nèi)存使用率,在絕大多數(shù)場(chǎng)景下使用這2種方式可確保Redis不會(huì)進(jìn)行內(nèi)存交換。倘若你擔(dān)心由于限制了內(nèi)存使用率導(dǎo)致丟失數(shù)據(jù)的話,可以設(shè)置noneviction值禁止淘汰數(shù)據(jù)。

          命令處理數(shù)total_commands_processed

          在info信息里的total_commands_processed字段顯示了Redis服務(wù)處理命令的總數(shù),其命令都是從一個(gè)或多個(gè)Redis客戶(hù)端請(qǐng)求過(guò)來(lái)的。Redis每時(shí)每刻都在處理從客戶(hù)端請(qǐng)求過(guò)來(lái)的命令,它可以是Redis提供的140種命令的任意一個(gè)。total_commands_processed字段的值是遞增的,比如Redis服務(wù)分別處理了client_x請(qǐng)求過(guò)來(lái)的2個(gè)命令和client_y請(qǐng)求過(guò)來(lái)的3個(gè)命令,那么命令處理總數(shù)(total_commands_processed)就會(huì)加上5。

          分析命令處理總數(shù),診斷響應(yīng)延遲。

          在Redis實(shí)例中,跟蹤命令處理總數(shù)是解決響應(yīng)延遲問(wèn)題最關(guān)鍵的部分,因?yàn)镽edis是個(gè)單線程模型,客戶(hù)端過(guò)來(lái)的命令是按照順序執(zhí)行的。比較常見(jiàn)的延遲是帶寬,通過(guò)千兆網(wǎng)卡的延遲大約有200μs。倘若明顯看到命令的響應(yīng)時(shí)間變慢,延遲高于200μs,那可能是Redis命令隊(duì)列里等待處理的命令數(shù)量比較多。如上所述,延遲時(shí)間增加導(dǎo)致響應(yīng)時(shí)間變慢可能是由于一個(gè)或多個(gè)慢命令引起的,這時(shí)可以看到每秒命令處理數(shù)在明顯下降,甚至于后面的命令完全被阻塞,導(dǎo)致Redis性能降低。要分析解決這個(gè)性能問(wèn)題,需要跟蹤命令處理數(shù)的數(shù)量和延遲時(shí)間。

          比如可以寫(xiě)個(gè)腳本,定期記錄total_commands_processed的值。當(dāng)客戶(hù)端明顯發(fā)現(xiàn)響應(yīng)時(shí)間過(guò)慢時(shí),可以通過(guò)記錄的total_commands_processed歷史數(shù)據(jù)值來(lái)判斷命理處理總數(shù)是上升趨勢(shì)還是下降趨勢(shì),以便排查問(wèn)題。

          使用命令處理總數(shù)解決延遲時(shí)間增加。

          通過(guò)與記錄的歷史數(shù)據(jù)比較得知,命令處理總數(shù)確實(shí)是處于上升或下降狀態(tài),那么可能是有2個(gè)原因引起的:

          1、命令隊(duì)列里的命令數(shù)量過(guò)多,后面命令一直在等待中。
          2、幾個(gè)慢命令阻塞Redis。

          下面有三個(gè)辦法可以解決,因上面2條原因引起的響應(yīng)延遲問(wèn)題。

          1、使用多參數(shù)命令:若是客戶(hù)端在很短的時(shí)間內(nèi)發(fā)送大量的命令過(guò)來(lái),會(huì)發(fā)現(xiàn)響應(yīng)時(shí)間明顯變慢,這由于后面命令一直在等待隊(duì)列中前面大量命令執(zhí)行完畢。有個(gè)方法可以改善延遲問(wèn)題,就是通過(guò)單命令多參數(shù)的形式取代多命令單參數(shù)的形式。舉例來(lái)說(shuō),循環(huán)使用LSET命令去添加1000個(gè)元素到list結(jié)構(gòu)中,是性能比較差的一種方式,更好的做法是在客戶(hù)端創(chuàng)建一個(gè)1000元素的列表,用單個(gè)命令LPUSH或RPUSH,通過(guò)多參數(shù)構(gòu)造形式一次性把1000個(gè)元素發(fā)送的Redis服務(wù)上。下面的表格是Redis的一些操作命令,有單個(gè)參數(shù)命令和支持多個(gè)參數(shù)的命令,通過(guò)這些命令可盡量減少使用多命令的次數(shù)。 

          2、管道命令:另一個(gè)減少多命令的方法是使用管道(pipeline),把幾個(gè)命令合并一起執(zhí)行,從而減少因網(wǎng)絡(luò)開(kāi)銷(xiāo)引起的延遲問(wèn)題。因?yàn)?0個(gè)命令單獨(dú)發(fā)送到服務(wù)端會(huì)引起10次網(wǎng)絡(luò)延遲開(kāi)銷(xiāo),使用管道會(huì)一次性把執(zhí)行結(jié)果返回,僅需要一次網(wǎng)絡(luò)延遲開(kāi)銷(xiāo)。Redis本身支持管道命令,大多數(shù)客戶(hù)端也支持,倘若當(dāng)前實(shí)例延遲很明顯,那么使用管道去降低延遲是非常有效的。

          3、避免操作大集合的慢命令:如果命令處理頻率過(guò)低導(dǎo)致延遲時(shí)間增加,這可能是因?yàn)槭褂昧烁邥r(shí)間復(fù)雜度的命令操作導(dǎo)致,這意味著每個(gè)命令從集合中獲取數(shù)據(jù)的時(shí)間增大。所以減少使用高時(shí)間復(fù)雜的命令,能顯著的提高的Redis的性能。下面的表格是高時(shí)間復(fù)雜度命令的列表,其詳細(xì)描述了命令的屬性,有這助于高效合理的、最優(yōu)化的使用這些命令(如果不得不使用的話),以提高Redis性能。

          延遲時(shí)間

          Redis的延遲數(shù)據(jù)是無(wú)法從info信息中獲取的。倘若想要查看延遲時(shí)間,可以用 Redis-cli工具加--latency參數(shù)運(yùn)行,如:

          Redis-cli --latency -h 127.0.0.1 -p 6379

          其host和port是Redis實(shí)例的ip及端口。由于當(dāng)前服務(wù)器不同的運(yùn)行情況,延遲時(shí)間可能有所誤差,通常1G網(wǎng)卡的延遲時(shí)間是200μs。

          以毫秒為單位測(cè)量Redis的響應(yīng)延遲時(shí)間,樓主本機(jī)的延遲是300μs:

          跟蹤Redis延遲性能

          Redis之所以這么流行的主要原因之一就是低延遲特性帶來(lái)的高性能,所以說(shuō)解決延遲問(wèn)題是提高Redis性能最直接的辦法。拿1G帶寬來(lái)說(shuō),若是延遲時(shí)間遠(yuǎn)高于200μs,那明顯是出現(xiàn)了性能問(wèn)題。雖然在服務(wù)器上會(huì)有一些慢的IO操作,但Redis是單核接受所有客戶(hù)端的請(qǐng)求,所有請(qǐng)求是按良好的順序排隊(duì)執(zhí)行。因此若是一個(gè)客戶(hù)端發(fā)過(guò)來(lái)的命令是個(gè)慢操作,那么其他所有請(qǐng)求必須等待它完成后才能繼續(xù)執(zhí)行。

          使用延遲命令提高性能

          一旦確定延遲時(shí)間是個(gè)性能問(wèn)題后,這里有幾個(gè)辦法可以用來(lái)分析解決性能問(wèn)題。

          1. 使用slowlog查出引發(fā)延遲的慢命令:Redis中的slowlog命令可以讓我們快速定位到那些超出指定執(zhí)行時(shí)間的慢命令,默認(rèn)情況下命令若是執(zhí)行時(shí)間超過(guò)10ms就會(huì)被記錄到日志。slowlog只會(huì)記錄其命令執(zhí)行的時(shí)間,不包含io往返操作,也不記錄單由網(wǎng)絡(luò)延遲引起的響應(yīng)慢。通常1gb帶寬的網(wǎng)絡(luò)延遲,預(yù)期在200μs左右,倘若一個(gè)命令僅執(zhí)行時(shí)間就超過(guò)10ms,那比網(wǎng)絡(luò)延遲慢了近50倍。想要查看所有執(zhí)行時(shí)間比較慢的命令,可以通過(guò)使用Redis-cli工具,輸入slowlog get命令查看,返回結(jié)果的第三個(gè)字段以微妙位單位顯示命令的執(zhí)行時(shí)間。假如只需要查看最后10個(gè)慢命令,輸入slowlog get 10即可。關(guān)于怎么定位到是由慢命令引起的延遲問(wèn)題,可查看total_commands_processed介紹章節(jié)。

          圖中字段分別意思是:

          1、1=日志的唯一標(biāo)識(shí)符
          2、2=被記錄命令的執(zhí)行時(shí)間點(diǎn),以 UNIX 時(shí)間戳格式表示
          3、3=查詢(xún)執(zhí)行時(shí)間,以微秒為單位。例子中命令使用54毫秒。
          4、4=執(zhí)行的命令,以數(shù)組的形式排列。完整命令是config get *。

          倘若你想自定義慢命令的標(biāo)準(zhǔn),可以調(diào)整觸發(fā)日志記錄慢命令的閥值。若是很少或沒(méi)有命令超過(guò)10ms,想降低記錄的閥值,比如5毫秒,可在Redis-cli工具中輸入下面的命令配置:

          config set slowlog-log-slower-than 5000

          也可以在Redis.config配置文件中設(shè)置,以微妙位單位。

          2.監(jiān)控客戶(hù)端的連接:因?yàn)镽edis是單線程模型(只能使用單核),來(lái)處理所有客戶(hù)端的請(qǐng)求, 但由于客戶(hù)端連接數(shù)的增長(zhǎng),處理請(qǐng)求的線程資源開(kāi)始降低分配給單個(gè)客戶(hù)端連接的處理時(shí)間,這時(shí)每個(gè)客戶(hù)端需要花費(fèi)更多的時(shí)間去等待Redis共享服務(wù)的響應(yīng)。這種情況下監(jiān)控客戶(hù)端連接數(shù)是非常重要的,因?yàn)榭蛻?hù)端創(chuàng)建連接數(shù)的數(shù)量可能超出預(yù)期的數(shù)量,也可能是客戶(hù)端端沒(méi)有有效的釋放連接。在Redis-cli工具中輸入info clients可以查看到當(dāng)前實(shí)例的所有客戶(hù)端連接信息。如下圖,第一個(gè)字段(connected_clients)顯示當(dāng)前實(shí)例客戶(hù)端連接的總數(shù):

          Redis默認(rèn)允許客戶(hù)端連接的最大數(shù)量是10000。若是看到連接數(shù)超過(guò)5000以上,那可能會(huì)影響Redis的性能。倘若一些或大部分客戶(hù)端發(fā)送大量的命令過(guò)來(lái),這個(gè)數(shù)字會(huì)低的多。

          3.限制客戶(hù)端連接數(shù):自Redis2.6以后,允許使用者在配置文件(Redis.conf)maxclients屬性上修改客戶(hù)端連接的最大數(shù),也可以通過(guò)在Redis-cli工具上輸入config set maxclients 去設(shè)置最大連接數(shù)。根據(jù)連接數(shù)負(fù)載的情況,這個(gè)數(shù)字應(yīng)該設(shè)置為預(yù)期連接數(shù)峰值的110%到150之間,若是連接數(shù)超出這個(gè)數(shù)字后,Redis會(huì)拒絕并立刻關(guān)閉新來(lái)的連接。通過(guò)設(shè)置最大連接數(shù)來(lái)限制非預(yù)期數(shù)量的連接數(shù)增長(zhǎng),是非常重要的。另外,新連接嘗試失敗會(huì)返回一個(gè)錯(cuò)誤消息,這可以讓客戶(hù)端知道,Redis此時(shí)有非預(yù)期數(shù)量的連接數(shù),以便執(zhí)行對(duì)應(yīng)的處理措施。上述二種做法對(duì)控制連接數(shù)的數(shù)量和持續(xù)保持Redis的性能最優(yōu)是非常重要的,

          4.加強(qiáng)內(nèi)存管理:較少的內(nèi)存會(huì)引起Redis延遲時(shí)間增加。如果Redis占用內(nèi)存超出系統(tǒng)可用內(nèi)存,操作系統(tǒng)會(huì)把Redis進(jìn)程的一部分?jǐn)?shù)據(jù),從物理內(nèi)存交換到硬盤(pán)上,內(nèi)存交換會(huì)明顯的增加延遲時(shí)間。關(guān)于怎么監(jiān)控和減少內(nèi)存使用,可查看used_memory介紹章節(jié)。

          5. 性能數(shù)據(jù)指標(biāo):分析解決Redis性能問(wèn)題,通常需要把延遲時(shí)間的數(shù)據(jù)變化與其他性能指標(biāo)的變化相關(guān)聯(lián)起來(lái)。命令處理總數(shù)下降的發(fā)生可能是由慢命令阻塞了整個(gè)系統(tǒng),但如果命令處理總數(shù)的增加,同時(shí)內(nèi)存使用率也增加,那么就可能是由于內(nèi)存交換引起的性能問(wèn)題。對(duì)于這種性能指標(biāo)相關(guān)聯(lián)的分析,需要從歷史數(shù)據(jù)上來(lái)觀察到數(shù)據(jù)指標(biāo)的重要變化,此外還可以觀察到單個(gè)性能指標(biāo)相關(guān)聯(lián)的所有其他性能指標(biāo)信息。這些數(shù)據(jù)可以在Redis上收集,周期性的調(diào)用內(nèi)容為Redis info的腳本,然后分析輸出的信息,記錄到日志文件中。當(dāng)延遲發(fā)生變化時(shí),用日志文件配合其他數(shù)據(jù)指標(biāo),把數(shù)據(jù)串聯(lián)起來(lái)排查定位問(wèn)題。

          內(nèi)存碎片率

          info信息中的mem_fragmentation_ratio給出了內(nèi)存碎片率的數(shù)據(jù)指標(biāo),它是由操系統(tǒng)分配的內(nèi)存除以Redis分配的內(nèi)存得出:

          used_memory和used_memory_rss數(shù)字都包含的內(nèi)存分配有:

          1、用戶(hù)定義的數(shù)據(jù):內(nèi)存被用來(lái)存儲(chǔ)key-value值。
          2、內(nèi)部開(kāi)銷(xiāo):存儲(chǔ)內(nèi)部Redis信息用來(lái)表示不同的數(shù)據(jù)類(lèi)型。

          used_memory_rss的rss是Resident Set Size的縮寫(xiě),表示該進(jìn)程所占物理內(nèi)存的大小,是操作系統(tǒng)分配給Redis實(shí)例的內(nèi)存大小。除了用戶(hù)定義的數(shù)據(jù)和內(nèi)部開(kāi)銷(xiāo)以外,used_memory_rss指標(biāo)還包含了內(nèi)存碎片的開(kāi)銷(xiāo),內(nèi)存碎片是由操作系統(tǒng)低效的分配/回收物理內(nèi)存導(dǎo)致的。

          操作系統(tǒng)負(fù)責(zé)分配物理內(nèi)存給各個(gè)應(yīng)用進(jìn)程,Redis使用的內(nèi)存與物理內(nèi)存的映射是由操作系統(tǒng)上虛擬內(nèi)存管理分配器完成的。

          舉個(gè)例子來(lái)說(shuō),Redis需要分配連續(xù)內(nèi)存塊來(lái)存儲(chǔ)1G的數(shù)據(jù)集,這樣的話更有利,但可能物理內(nèi)存上沒(méi)有超過(guò)1G的連續(xù)內(nèi)存塊,那操作系統(tǒng)就不得不使用多個(gè)不連續(xù)的小內(nèi)存塊來(lái)分配并存儲(chǔ)這1G數(shù)據(jù),也就導(dǎo)致內(nèi)存碎片的產(chǎn)生。
          內(nèi)存分配器另一個(gè)復(fù)雜的層面是,它經(jīng)常會(huì)預(yù)先分配一些內(nèi)存塊給引用,這樣做會(huì)使加快應(yīng)用程序的運(yùn)行。

          理解資源性能

          跟蹤內(nèi)存碎片率對(duì)理解Redis實(shí)例的資源性能是非常重要的。內(nèi)存碎片率稍大于1是合理的,這個(gè)值表示內(nèi)存碎片率比較低,也說(shuō)明redis沒(méi)有發(fā)生內(nèi)存交換。但如果內(nèi)存碎片率超過(guò)1.5,那就說(shuō)明Redis消耗了實(shí)際需要物理內(nèi)存的150%,其中50%是內(nèi)存碎片率。若是內(nèi)存碎片率低于1的話,說(shuō)明Redis內(nèi)存分配超出了物理內(nèi)存,操作系統(tǒng)正在進(jìn)行內(nèi)存交換。內(nèi)存交換會(huì)引起非常明顯的響應(yīng)延遲,可查看used_memory介紹章節(jié)。

          上圖中的0.99即99%。

          用內(nèi)存碎片率預(yù)測(cè)性能問(wèn)題

          倘若內(nèi)存碎片率超過(guò)了1.5,那可能是操作系統(tǒng)或Redis實(shí)例中內(nèi)存管理變差的表現(xiàn)。下面有3種方法解決內(nèi)存管理變差的問(wèn)題,并提高Redis性能:

          1. 重啟Redis服務(wù)器:如果內(nèi)存碎片率超過(guò)1.5,重啟Redis服務(wù)器可以讓額外產(chǎn)生的內(nèi)存碎片失效并重新作為新內(nèi)存來(lái)使用,使操作系統(tǒng)恢復(fù)高效的內(nèi)存管理。額外碎片的產(chǎn)生是由于Redis釋放了內(nèi)存塊,但內(nèi)存分配器并沒(méi)有返回內(nèi)存給操作系統(tǒng),這個(gè)內(nèi)存分配器是在編譯時(shí)指定的,可以是libc、jemalloc或者tcmalloc。通過(guò)比較used_memory_peak, used_memory_rss和used_memory_metrics的數(shù)據(jù)指標(biāo)值可以檢查額外內(nèi)存碎片的占用。從名字上可以看出,used_memory_peak是過(guò)去Redis內(nèi)存使用的峰值,而不是當(dāng)前使用內(nèi)存的值。如果used_memory_peak和used_memory_rss的值大致上相等,而且二者明顯超過(guò)了used_memory值,這說(shuō)明額外的內(nèi)存碎片正在產(chǎn)生。在Redis-cli工具上輸入info memory可以查看上面三個(gè)指標(biāo)的信息:

          在重啟服務(wù)器之前,需要在Redis-cli工具上輸入shutdown save命令,意思是強(qiáng)制讓Redis數(shù)據(jù)庫(kù)執(zhí)行保存操作并關(guān)閉Redis服務(wù),這樣做能保證在執(zhí)行Redis關(guān)閉時(shí)不丟失任何數(shù)據(jù)。在重啟后,Redis會(huì)從硬盤(pán)上加載持久化的文件,以確保數(shù)據(jù)集持續(xù)可用。

          2.限制內(nèi)存交換:如果內(nèi)存碎片率低于1,Redis實(shí)例可能會(huì)把部分?jǐn)?shù)據(jù)交換到硬盤(pán)上。內(nèi)存交換會(huì)嚴(yán)重影響Redis的性能,所以應(yīng)該增加可用物理內(nèi)存或減少實(shí)Redis內(nèi)存占用。可查看used_memory章節(jié)的優(yōu)化建議。

          3.修改內(nèi)存分配器:Redis支持glibc’s malloc、jemalloc11、tcmalloc幾種不同的內(nèi)存分配器,每個(gè)分配器在內(nèi)存分配和碎片上都有不同的實(shí)現(xiàn)。不建議普通管理員修改Redis默認(rèn)內(nèi)存分配器,因?yàn)檫@需要完全理解這幾種內(nèi)存分配器的差異,也要重新編譯Redis。這個(gè)方法更多的是讓其了解Redis內(nèi)存分配器所做的工作,當(dāng)然也是改善內(nèi)存碎片問(wèn)題的一種辦法。

          回收key

          info信息中的evicted_keys字段顯示的是,因?yàn)閙axmemory限制導(dǎo)致key被回收刪除的數(shù)量。關(guān)于maxmemory的介紹見(jiàn)前面章節(jié),回收key的情況只會(huì)發(fā)生在設(shè)置maxmemory值后,不設(shè)置會(huì)發(fā)生內(nèi)存交換。當(dāng)Redis由于內(nèi)存壓力需要回收一個(gè)key時(shí),Redis首先考慮的不是回收最舊的數(shù)據(jù),而是在最近最少使用的key或即將過(guò)期的key中隨機(jī)選擇一個(gè)key,從數(shù)據(jù)集中刪除。

          這可以在配置文件中設(shè)置maxmemory-policy值為“volatile-lru”或“volatile-ttl”,來(lái)確定Redis是使用lru策略還是過(guò)期時(shí)間策略。倘若所有的key都有明確的過(guò)期時(shí)間,那過(guò)期時(shí)間回收策略是比較合適的。若是沒(méi)有設(shè)置key的過(guò)期時(shí)間或者說(shuō)沒(méi)有足夠的過(guò)期key,那設(shè)置lru策略是比較合理的,這可以回收key而不用考慮其過(guò)期狀態(tài)。

          根據(jù)key回收定位性能問(wèn)題

          跟蹤key回收是非常重要的,因?yàn)橥ㄟ^(guò)回收key,可以保證合理分配Redis有限的內(nèi)存資源。如果evicted_keys值經(jīng)常超過(guò)0,那應(yīng)該會(huì)看到客戶(hù)端命令響應(yīng)延遲時(shí)間增加,因?yàn)镽edis不但要處理客戶(hù)端過(guò)來(lái)的命令請(qǐng)求,還要頻繁的回收滿(mǎn)足條件的key。

          需要注意的是,回收key對(duì)性能的影響遠(yuǎn)沒(méi)有內(nèi)存交換嚴(yán)重,若是在強(qiáng)制內(nèi)存交換和設(shè)置回收策略做一個(gè)選擇的話,選擇設(shè)置回收策略是比較合理的,因?yàn)榘褍?nèi)存數(shù)據(jù)交換到硬盤(pán)上對(duì)性能影響非常大。

          減少回收key以提升性能

          減少回收key的數(shù)量是提升Redis性能的直接辦法,下面有2種方法可以減少回收key的數(shù)量:

          1.增加內(nèi)存限制:倘若開(kāi)啟快照功能,maxmemory需要設(shè)置成物理內(nèi)存的45%,這幾乎不會(huì)有引發(fā)內(nèi)存交換的危險(xiǎn)。若是沒(méi)有開(kāi)啟快照功能,設(shè)置系統(tǒng)可用內(nèi)存的95%是比較合理的,具體參考前面的快照和maxmemory限制章節(jié)。如果maxmemory的設(shè)置是低于45%或95%(視持久化策略),通過(guò)增加maxmemory的值能讓Redis在內(nèi)存中存儲(chǔ)更多的key,這能顯著減少回收key的數(shù)量。若是maxmemory已經(jīng)設(shè)置為推薦的閥值后,增加maxmemory限制不但無(wú)法提升性能,反而會(huì)引發(fā)內(nèi)存交換,導(dǎo)致延遲增加、性能降低。maxmemory的值可以在Redis-cli工具上輸入config set maxmemory命令來(lái)設(shè)置。

          需要注意的是,這個(gè)設(shè)置是立即生效的,但重啟后丟失,需要永久化保存的話,再輸入config rewrite命令會(huì)把內(nèi)存中的新配置刷新到配置文件中。

          2.對(duì)實(shí)例進(jìn)行分片:分片是把數(shù)據(jù)分割成合適大小,分別存放在不同的Redis實(shí)例上,每一個(gè)實(shí)例都包含整個(gè)數(shù)據(jù)集的一部分。通過(guò)分片可以把很多服務(wù)器聯(lián)合起來(lái)存儲(chǔ)數(shù)據(jù),相當(dāng)于增加總的物理內(nèi)存,使其在沒(méi)有內(nèi)存交換和回收key的策略下也能存儲(chǔ)更多的key。假如有一個(gè)非常大的數(shù)據(jù)集,maxmemory已經(jīng)設(shè)置,實(shí)際內(nèi)存使用也已經(jīng)超過(guò)了推薦設(shè)置的閥值,那通過(guò)數(shù)據(jù)分片能明顯減少key的回收,從而提高Redis的性能。分片的實(shí)現(xiàn)有很多種方法,下面是Redis實(shí)現(xiàn)分片的幾種常見(jiàn)方式:

          a. Hash分片:一個(gè)比較簡(jiǎn)單的方法實(shí)現(xiàn),通過(guò)Hash函數(shù)計(jì)算出key的Hash值,然后值所在范圍對(duì)應(yīng)特定的Redis實(shí)例。
          b. 代理分片:客戶(hù)端把請(qǐng)求發(fā)送到代理上,代理通過(guò)分片配置表選擇對(duì)應(yīng)的Redis實(shí)例。如Twitter的Twemproxy,豌豆莢的codis。
          c. 一致性Hash分片
          d. 虛擬桶分片

          總結(jié)

          對(duì)于開(kāi)發(fā)者來(lái)說(shuō),Redis是個(gè)速度非常快的key-value內(nèi)存數(shù)據(jù)庫(kù),并提供了方便的API接口。為了最好最優(yōu)的使用Redis,需要理解哪些因素能影響到Redis性能,哪些數(shù)據(jù)指標(biāo)能幫助我們避免性能陷阱。通過(guò)本篇,能理解Redis中的重要性能指標(biāo),怎么查看,更重要的是怎么利用這些數(shù)據(jù)排查解決Redis性能問(wèn)題。

          本篇文章還翻譯了一電子書(shū)的中間15頁(yè),電子書(shū)可以在公眾號(hào)后臺(tái)回復(fù):Redis性能 獲取。

          來(lái)源:https://www.cnblogs.com/mushroom/p/4738170.html

          推薦閱讀

          Redis是什么?看這一篇就夠了!

          推薦幾款 Redis 可視化工具

          學(xué) Redis,至少要看看這篇!7000 字小結(jié)

          史上最全 Redis 總結(jié),你想知道的都在這里啦!

          Redis 使用的 10 個(gè)小技巧!

          Redis 性能監(jiān)控指標(biāo)匯總

          大廠面試!我和面試官之間關(guān)于Redis的一場(chǎng)對(duì)弈!

          瀏覽 30
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  中文字幕妻人久久黑人 | 91天天综合网,天天综合网 | 色欲欲www成人网站 | 国产无套精品久久久久久 | 影音先锋在线资源自拍 |