站長(zhǎng)資訊網(wǎng)
最全最豐富的資訊網(wǎng)站

淺談Redis變慢的原因及排查方法

本篇文章給大家?guī)砹岁P(guān)于Redis的相關(guān)知識(shí),其中主要介紹了淺談Redis變慢的原因及排查方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,下面一起來看一下,希望對(duì)大家有幫助。

淺談Redis變慢的原因及排查方法

推薦學(xué)習(xí):Redis視頻教程

原因1:實(shí)例內(nèi)存達(dá)到上限

排查思路

如果你的 Redis 實(shí)例設(shè)置了內(nèi)存上限 maxmemory,那么也有可能導(dǎo)致 Redis 變慢。

當(dāng)我們把 Redis 當(dāng)做純緩存使用時(shí),通常會(huì)給這個(gè)實(shí)例設(shè)置一個(gè)內(nèi)存上限 maxmemory,然后設(shè)置一個(gè)數(shù)據(jù)淘汰策略。而當(dāng)實(shí)例的內(nèi)存達(dá)到了 maxmemory 后,你可能會(huì)發(fā)現(xiàn),在此之后每次寫入新數(shù)據(jù),操作延遲變大了。

導(dǎo)致變慢的原因

當(dāng) Redis 內(nèi)存達(dá)到 maxmemory 后,每次寫入新的數(shù)據(jù)之前,Redis 必須先從實(shí)例中踢出一部分?jǐn)?shù)據(jù),讓整個(gè)實(shí)例的內(nèi)存維持在 maxmemory 之下,然后才能把新數(shù)據(jù)寫進(jìn)來。

這個(gè)踢出舊數(shù)據(jù)的邏輯也是需要消耗時(shí)間的,而具體耗時(shí)的長(zhǎng)短,要取決于你配置的淘汰策略:

  • allkeys-lru:不管 key 是否設(shè)置了過期,淘汰最近最少訪問的 key
  • volatile-lru:只淘汰最近最少訪問、并設(shè)置了過期時(shí)間的 key
  • allkeys-random:不管 key 是否設(shè)置了過期,隨機(jī)淘汰 key
  • volatile-random:只隨機(jī)淘汰設(shè)置了過期時(shí)間的 key
  • allkeys-ttl:不管 key 是否設(shè)置了過期,淘汰即將過期的 key
  • noeviction:不淘汰任何 key,實(shí)例內(nèi)存達(dá)到 maxmeory 后,再寫入新數(shù)據(jù)直接返回錯(cuò)誤
  • allkeys-lfu:不管 key 是否設(shè)置了過期,淘汰訪問頻率最低的 key(4.0+版本支持)
  • volatile-lfu:只淘汰訪問頻率最低、并設(shè)置了過期時(shí)間 key(4.0+版本支持)

具體使用哪種策略,我們需要根據(jù)具體的業(yè)務(wù)場(chǎng)景來配置。一般最常使用的是 allkeys-lru / volatile-lru 淘汰策略,它們的處理邏輯是,每次從實(shí)例中隨機(jī)取出一批 key(這個(gè)數(shù)量可配置),然后淘汰一個(gè)最少訪問的 key,之后把剩下的 key 暫存到一個(gè)池子中,繼續(xù)隨機(jī)取一批 key,并與之前池子中的 key 比較,再淘汰一個(gè)最少訪問的 key。以此往復(fù),直到實(shí)例內(nèi)存降到 maxmemory 之下。

需要注意的是,Redis 的淘汰數(shù)據(jù)的邏輯與刪除過期 key 的一樣,也是在命令真正執(zhí)行之前執(zhí)行的,也就是說它也會(huì)增加我們操作 Redis 的延遲,而且,寫 OPS 越高,延遲也會(huì)越明顯。

淺談Redis變慢的原因及排查方法

另外,如果此時(shí)你的 Redis 實(shí)例中還存儲(chǔ)了 bigkey,那么在淘汰刪除 bigkey 釋放內(nèi)存時(shí),也會(huì)耗時(shí)比較久。

看到了么?bigkey 的危害到處都是,這也是前面我提醒你盡量不存儲(chǔ) bigkey 的原因。

解決方案

  • 避免存儲(chǔ) bigkey,降低釋放內(nèi)存的耗時(shí)
  • 淘汰策略改為隨機(jī)淘汰,隨機(jī)淘汰比 LRU 要快很多(視業(yè)務(wù)情況調(diào)整)
  • 拆分實(shí)例,把淘汰 key 的壓力分?jǐn)偟蕉鄠€(gè)實(shí)例上
  • 如果使用的是 Redis 4.0 以上版本,開啟 layz-free 機(jī)制,把淘汰 key 釋放內(nèi)存的操作放到后臺(tái)線程中執(zhí)行(配置 lazyfree-lazy-eviction = yes)

原因2:開啟內(nèi)存大頁

排查思路

  • 我們都知道,應(yīng)用程序向操作系統(tǒng)申請(qǐng)內(nèi)存時(shí),是按內(nèi)存頁進(jìn)行申請(qǐng)的,而常規(guī)的內(nèi)存頁大小是 4KB。
  • Linux 內(nèi)核從 2.6.38 開始,支持了內(nèi)存大頁機(jī)制,該機(jī)制允許應(yīng)用程序以 2MB 大小為單位,向操作系統(tǒng)申請(qǐng)內(nèi)存。
  • 應(yīng)用程序每次向操作系統(tǒng)申請(qǐng)的內(nèi)存單位變大了,但這也意味著申請(qǐng)內(nèi)存的耗時(shí)變長(zhǎng)。

導(dǎo)致變慢的原因

  • 當(dāng) Redis 在執(zhí)行后臺(tái) RDB 和 AOF rewrite 時(shí),采用 fork 子進(jìn)程的方式來處理。但主進(jìn)程 fork 子進(jìn)程后,此時(shí)的主進(jìn)程依舊是可以接收寫請(qǐng)求的,而進(jìn)來的寫請(qǐng)求,會(huì)采用 Copy On Write(寫時(shí)復(fù)制)的方式操作內(nèi)存數(shù)據(jù)。
  • 也就是說,主進(jìn)程一旦有數(shù)據(jù)需要修改,Redis 并不會(huì)直接修改現(xiàn)有內(nèi)存中的數(shù)據(jù),而是先將這塊內(nèi)存數(shù)據(jù)拷貝出來,再修改這塊新內(nèi)存的數(shù)據(jù),這就是所謂的「寫時(shí)復(fù)制」。
  • 寫時(shí)復(fù)制你也可以理解成,誰需要發(fā)生寫操作,誰就需要先拷貝,再修改。
  • 這樣做的好處是,父進(jìn)程有任何寫操作,并不會(huì)影響子進(jìn)程的數(shù)據(jù)持久化(子進(jìn)程只持久化 fork 這一瞬間整個(gè)實(shí)例中的所有數(shù)據(jù)即可,不關(guān)心新的數(shù)據(jù)變更,因?yàn)樽舆M(jìn)程只需要一份內(nèi)存快照,然后持久化到磁盤上)。
  • 但是請(qǐng)注意,主進(jìn)程在拷貝內(nèi)存數(shù)據(jù)時(shí),這個(gè)階段就涉及到新內(nèi)存的申請(qǐng),如果此時(shí)操作系統(tǒng)開啟了內(nèi)存大頁,那么在此期間,客戶端即便只修改 10B 的數(shù)據(jù),Redis 在申請(qǐng)內(nèi)存時(shí)也會(huì)以 2MB 為單位向操作系統(tǒng)申請(qǐng),申請(qǐng)內(nèi)存的耗時(shí)變長(zhǎng),進(jìn)而導(dǎo)致每個(gè)寫請(qǐng)求的延遲增加,影響到 Redis 性能。
  • 同樣地,如果這個(gè)寫請(qǐng)求操作的是一個(gè) bigkey,那主進(jìn)程在拷貝這個(gè) bigkey 內(nèi)存塊時(shí),一次申請(qǐng)的內(nèi)存會(huì)更大,時(shí)間也會(huì)更久。可見,bigkey 在這里又一次影響到了性能。

淺談Redis變慢的原因及排查方法

解決方案

關(guān)閉內(nèi)存大頁機(jī)制。

首先,你需要查看 Redis 機(jī)器是否開啟了內(nèi)存大頁:

$ cat /sys/kernel/mm/transparent_hugepage/enabled [always] madvise never

如果輸出選項(xiàng)是 always,就表示目前開啟了內(nèi)存大頁機(jī)制,我們需要關(guān)掉它:

$ echo never > /sys/kernel/mm/transparent_hugepage/enabled

其實(shí),操作系統(tǒng)提供的內(nèi)存大頁機(jī)制,其優(yōu)勢(shì)是,可以在一定程序上降低應(yīng)用程序申請(qǐng)內(nèi)存的次數(shù)。

但是對(duì)于 Redis 這種對(duì)性能和延遲極其敏感的數(shù)據(jù)庫來說,我們希望 Redis 在每次申請(qǐng)內(nèi)存時(shí),耗時(shí)盡量短,所以我不建議你在 Redis 機(jī)器上開啟這個(gè)機(jī)制。

原因3:使用Swap

排查思路

如果你發(fā)現(xiàn) Redis 突然變得非常慢,每次的操作耗時(shí)都達(dá)到了幾百毫秒甚至秒級(jí),那此時(shí)你就需要檢查 Redis 是否使用到了 Swap,在這種情況下 Redis 基本上已經(jīng)無法提供高性能的服務(wù)了。

導(dǎo)致變慢的原因

什么是 Swap?為什么使用 Swap 會(huì)導(dǎo)致 Redis 的性能下降?

如果你對(duì)操作系統(tǒng)有些了解,就會(huì)知道操作系統(tǒng)為了緩解內(nèi)存不足對(duì)應(yīng)用程序的影響,允許把一部分內(nèi)存中的數(shù)據(jù)換到磁盤上,以達(dá)到應(yīng)用程序?qū)?nèi)存使用的緩沖,這些內(nèi)存數(shù)據(jù)被換到磁盤上的區(qū)域,就是 Swap。

問題就在于,當(dāng)內(nèi)存中的數(shù)據(jù)被換到磁盤上后,Redis 再訪問這些數(shù)據(jù)時(shí),就需要從磁盤上讀取,訪問磁盤的速度要比訪問內(nèi)存慢幾百倍!尤其是針對(duì) Redis 這種對(duì)性能要求極高、性能極其敏感的數(shù)據(jù)庫來說,這個(gè)操作延時(shí)是無法接受的。

此時(shí),你需要檢查 Redis 機(jī)器的內(nèi)存使用情況,確認(rèn)是否存在使用了 Swap。你可以通過以下方式來查看 Redis 進(jìn)程是否使用到了 Swap:

# 先找到 Redis 的進(jìn)程 ID $ ps -aux | grep redis-server   # 查看 Redis Swap 使用情況 $ cat /proc/$pid/smaps | egrep '^(Swap|Size)'

輸出結(jié)果如下

Size: 1256 kB
Swap: 0 kB
Size: 4 kB
Swap: 0 kB
Size: 132 kB
Swap: 0 kB
Size: 63488 kB
Swap: 0 kB
Size: 132 kB
Swap: 0 kB
Size: 65404 kB
Swap: 0 kB
Size: 1921024 kB
Swap: 0 kB

這個(gè)結(jié)果會(huì)列出 Redis 進(jìn)程的內(nèi)存使用情況。

每一行 Size 表示 Redis 所用的一塊內(nèi)存大小,Size 下面的 Swap 就表示這塊 Size 大小的內(nèi)存,有多少數(shù)據(jù)已經(jīng)被換到磁盤上了,如果這兩個(gè)值相等,說明這塊內(nèi)存的數(shù)據(jù)都已經(jīng)完全被換到磁盤上了。

如果只是少量數(shù)據(jù)被換到磁盤上,例如每一塊 Swap 占對(duì)應(yīng) Size 的比例很小,那影響并不是很大。如果是幾百兆甚至上 GB 的內(nèi)存被換到了磁盤上,那么你就需要警惕了,這種情況 Redis 的性能肯定會(huì)急劇下降。

解決方案

  • 增加機(jī)器的內(nèi)存,讓 Redis 有足夠的內(nèi)存可以使用
  • 整理內(nèi)存空間,釋放出足夠的內(nèi)存供 Redis 使用,然后釋放 Redis 的 Swap,讓 Redis 重新使用內(nèi)存

釋放 Redis 的 Swap 過程通常要重啟實(shí)例,為了避免重啟實(shí)例對(duì)業(yè)務(wù)的影響,一般會(huì)先進(jìn)行主從切換,然后釋放舊主節(jié)點(diǎn)的 Swap,重啟舊主節(jié)點(diǎn)實(shí)例,待從庫數(shù)據(jù)同步完成后,再進(jìn)行主從切換即可。

可見,當(dāng) Redis 使用到 Swap 后,此時(shí)的 Redis 性能基本已達(dá)不到高性能的要求(你可以理解為武功被廢),所以你也需要提前預(yù)防這種情況。

預(yù)防的辦法就是,你需要對(duì) Redis 機(jī)器的內(nèi)存和 Swap 使用情況進(jìn)行監(jiān)控,在內(nèi)存不足或使用到 Swap 時(shí)報(bào)警出來,及時(shí)處理。

原因4:網(wǎng)絡(luò)帶寬過載

排查思路

如果以上產(chǎn)生性能問題的場(chǎng)景,你都規(guī)避掉了,而且 Redis 也穩(wěn)定運(yùn)行了很長(zhǎng)時(shí)間,但在某個(gè)時(shí)間點(diǎn)之后開始,操作 Redis 突然開始變慢了,而且一直持續(xù)下去,這種情況又是什么原因?qū)е拢?/p>

此時(shí)你需要排查一下 Redis 機(jī)器的網(wǎng)絡(luò)帶寬是否過載,是否存在某個(gè)實(shí)例把整個(gè)機(jī)器的網(wǎng)路帶寬占滿的情況。

導(dǎo)致變慢的原因

網(wǎng)絡(luò)帶寬過載的情況下,服務(wù)器在 TCP 層和網(wǎng)絡(luò)層就會(huì)出現(xiàn)數(shù)據(jù)包發(fā)送延遲、丟包等情況。

Redis 的高性能,除了操作內(nèi)存之外,就在于網(wǎng)絡(luò) IO 了,如果網(wǎng)絡(luò) IO 存在瓶頸,那么也會(huì)嚴(yán)重影響 Redis 的性能。

解決方案

  • 及時(shí)確認(rèn)占滿網(wǎng)絡(luò)帶寬 Redis 實(shí)例,如果屬于正常的業(yè)務(wù)訪問,那就需要及時(shí)擴(kuò)容或遷移實(shí)例了,避免因?yàn)檫@個(gè)實(shí)例流量過大,影響這個(gè)機(jī)器的其他實(shí)例。
  • 運(yùn)維層面,你需要對(duì) Redis 機(jī)器的各項(xiàng)指標(biāo)增加監(jiān)控,包括網(wǎng)絡(luò)流量,在網(wǎng)絡(luò)流量達(dá)到一定閾值時(shí)提前報(bào)警,及時(shí)確認(rèn)和擴(kuò)容。

原因5:其他原因

1) 頻繁短連接

你的業(yè)務(wù)應(yīng)用,應(yīng)該使用長(zhǎng)連接操作 Redis,避免頻繁的短連接。

頻繁的短連接會(huì)導(dǎo)致 Redis 大量時(shí)間耗費(fèi)在連接的建立和釋放上,TCP 的三次握手和四次揮手同樣也會(huì)增加訪問延遲。

2) 運(yùn)維監(jiān)控

前面我也提到了,要想提前預(yù)知 Redis 變慢的情況發(fā)生,必不可少的就是做好完善的監(jiān)控。

監(jiān)控其實(shí)就是對(duì)采集 Redis 的各項(xiàng)運(yùn)行時(shí)指標(biāo),通常的做法是監(jiān)控程序定時(shí)采集 Redis 的 INFO 信息,然后根據(jù) INFO 信息中的狀態(tài)數(shù)據(jù)做數(shù)據(jù)展示和報(bào)警。

這里我需要提醒你的是,在寫一些監(jiān)控腳本,或使用開源的監(jiān)控組件時(shí),也不能掉以輕心。

在寫監(jiān)控腳本訪問 Redis 時(shí),盡量采用長(zhǎng)連接的方式采集狀態(tài)信息,避免頻繁短連接。同時(shí),你還要注意控制訪問 Redis 的頻率,避免影響到業(yè)務(wù)請(qǐng)求。

在使用一些開源的監(jiān)控組件時(shí),最好了解一下這些組件的實(shí)現(xiàn)原理,以及正確配置這些組件,防止出現(xiàn)監(jiān)控組件發(fā)生 Bug,導(dǎo)致短時(shí)大量操作 Redis,影響 Redis 性能的情況發(fā)生。

我們當(dāng)時(shí)就發(fā)生過,DBA 在使用一些開源組件時(shí),因?yàn)榕渲煤褪褂脝栴},導(dǎo)致監(jiān)控程序頻繁地與 Redis 建立和斷開連接,導(dǎo)致 Redis 響應(yīng)變慢。

3)其它程序爭(zhēng)搶資源

最后需要提醒你的是,你的 Redis 機(jī)器最好專項(xiàng)專用,只用來部署 Redis 實(shí)例,不要部署其他應(yīng)用程序,盡量給 Redis 提供一個(gè)相對(duì)「安靜」的環(huán)境,避免其它程序占用 CPU、內(nèi)存、磁盤資源,導(dǎo)致分配給 Redis 的資源不足而受到影響。

推薦學(xué)習(xí):Redis視頻教程

贊(0)
分享到: 更多 (0)
網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)
2021国产成人精品国产| 亚洲av永久无码精品古装片 | 亚洲色精品三区二区一区| 99久久99久久精品免费观看 | 国产精品成人不卡在线观看| 99re热视频精品首页| 久久久精品中文字幕麻豆发布| 中文无码精品一区二区三区| 国产乱码伦精品一区二区三区麻豆| 日韩精品中文字幕视频一区| 亚洲日韩精品无码专区网站| 国产精品天天在线| 在线观看麻豆精品国产不卡| 国产成人精品一区二区A片带套| 亚洲精品无码一区二区| 亚洲中文字幕久久精品无码VA | 日韩成人无码中文字幕| 国产精品久久久久久久网站| 国产日韩精品一区二区在线观看播放| 精品久久久无码中字| 日本一区二区三区精品视频| 日本精品视频在线播放| 国产色婷婷精品免费视频| 精品无码国产一区二区三区麻豆| 国产精品乱码一区二区三| 成人精品一区二区电影| 国产精品夜夜春夜夜爽久久小| 精品熟女少妇AV免费观看| 在线播放精品一区二区啪视频| 成人精品一区二区不卡视频| 视频久re精品在线观看| 国产精品嫩草影院免费| 国产九九久久99精品影院| 中文字幕日韩精品无码内射| 亚洲处破女AV日韩精品| 日韩欧毛片免费视频| 日韩中文字幕在线免费观看| 色婷婷久久久SWAG精品| 亚洲国产成人精品无码久久久久久综合| 老司机午夜精品视频在线观看免费| 无码人妻一区二区三区精品视频|