Redis慢查詢的具體使用
什么是Redis慢查詢?
redis的"慢查詢"與redis定義慢查詢的時(shí)間閾值有關(guān),Redis提供了slowlog-log-slower-than和slowlog-max-len兩個(gè)配置,slowlog-log-slower-than指當(dāng)redis命令的執(zhí)行時(shí)間超過該值時(shí),redis會(huì)將其記錄在redis的慢查詢?nèi)罩局?,slowlog-max-len表示記錄的條數(shù)(超過時(shí)會(huì)只存儲(chǔ)最新的slowlog-max-len條),slowlog-log-slower-than的默認(rèn)值為10000us,也就是一般來說,redis命令執(zhí)行時(shí)間超過10ms時(shí),我們認(rèn)為產(chǎn)生了慢查詢,redis慢查詢?nèi)罩居涗浀氖菆?zhí)行時(shí)間,沒有慢查詢,并不表示客戶端沒有超時(shí)問題,有可能網(wǎng)絡(luò)傳輸有延遲,也有可能排隊(duì)的命令比較多,導(dǎo)致redis查詢也很慢。
產(chǎn)生慢查詢有哪些原因?
在業(yè)務(wù)使用過程中,我們發(fā)現(xiàn)redis使用上出現(xiàn)慢查詢的原因有主要以下幾種:
- 使用復(fù)雜度過高的命令
- 大key問題
- 集中過期
如何解決慢查詢問題?
針對(duì)上述的原因,下面逐個(gè)給出導(dǎo)致慢查詢的原因細(xì)節(jié),并提出對(duì)應(yīng)解決redis慢查詢的有效方法。
使用復(fù)雜度過高的命令
負(fù)責(zé)的命令一般指O(N)以上的命令,比如sort、sunion、zunionstore聚合類的命令,或是O(N)類的命令,但是N的值由于業(yè)務(wù)原因特別大。
對(duì)于O(N)以上的命令,redis在操作內(nèi)存數(shù)據(jù)時(shí),耗時(shí)過高,會(huì)耗費(fèi)更多的cpu資源,導(dǎo)致查詢變慢。對(duì)于O(N)類的命令,由于N的值特別大Redis 一次需要返回給客戶端的數(shù)據(jù)過多,更多時(shí)間花費(fèi)在數(shù)據(jù)協(xié)議的組裝和網(wǎng)絡(luò)傳輸過程中。
除此之外,我們都知道,Redis 是單線程處理客戶端請(qǐng)求的,如果你經(jīng)常使用以上命令,那么當(dāng) Redis 處理客戶端請(qǐng)求時(shí),一旦前面某個(gè)命令發(fā)生耗時(shí),就會(huì)導(dǎo)致后面的請(qǐng)求發(fā)生排隊(duì),對(duì)于客戶端來說,響應(yīng)延遲也會(huì)長。
針對(duì)此類原因,我們一般有以下兩個(gè)原則:
- 盡量不使用O(N)以上復(fù)雜度的命令,某些數(shù)據(jù)排序或聚合操作,可以放在客戶端處理。
- 執(zhí)行O(N)命令時(shí),保證 N 盡量的?。ㄍ扑] N <= 300 經(jīng)驗(yàn)值),每次獲取盡量少的數(shù)據(jù),讓 Redis 可以及時(shí)處理返回。
大key問題
所謂大key問題其實(shí)并不是值key過大,實(shí)則值key對(duì)應(yīng)的value的值過大,此類問題在SET / DEL這類命令中也常出現(xiàn)慢查詢。
首先我們要了解下redis寫入與刪除數(shù)據(jù)做了什么:
- 寫入數(shù)據(jù):為該數(shù)據(jù)分配內(nèi)存。
- 刪除數(shù)據(jù):釋放該數(shù)據(jù)對(duì)應(yīng)的內(nèi)存空間。
很明顯,當(dāng)數(shù)據(jù)值比較大時(shí),redis分配數(shù)據(jù)內(nèi)存或釋放空間內(nèi)存都會(huì)比較耗時(shí),針對(duì)大key問題,有以下建議:
- 盡量避免寫入大key(不要寫入無關(guān)的數(shù)據(jù),數(shù)據(jù)實(shí)在過大可以進(jìn)行拆分,通過多key存儲(chǔ))
- 如果你使用的 Redis 是 4.0 以上版本,用 UNLINK 命令替代 DEL,此命令可以把釋放 key 內(nèi)存的操作,放到后臺(tái)線程中去執(zhí)行,從而降低對(duì) Redis 的影響
- 如果你使用的 Redis 是 6.0 以上版本,可以開啟 lazy-free 機(jī)制(lazyfree-lazy-user-del = yes),在執(zhí)行 DEL 命令時(shí),釋放內(nèi)存也會(huì)放到后臺(tái)線程中執(zhí)行。
順邊提下檢測大key的一個(gè)命令:
redis-cli -h 127.0.0.1 -p 6379 --bigkeys -i 0.01
輸出結(jié)果會(huì)展示每種數(shù)據(jù)類型所占用的最大內(nèi)存 / 擁有最多元素的 key 是哪一個(gè),以及每種數(shù)據(jù)類型在整個(gè)實(shí)例中的占比和平均大小 / 元素?cái)?shù)量。
其實(shí),使用這個(gè)命令的原理,就是 Redis 在內(nèi)部執(zhí)行了 SCAN 命令,遍歷整個(gè)實(shí)例中所有的 key,然后針對(duì) key 的類型,分別執(zhí)行 STRLEN、LLEN、HLEN、SCARD、ZCARD 命令,來獲取 String 類型的長度、容器類型(List、Hash、Set、ZSet)的元素個(gè)數(shù)。
這里我需要提醒你的是,當(dāng)執(zhí)行這個(gè)命令時(shí),要注意 2 個(gè)問題:
- 對(duì)線上實(shí)例進(jìn)行 bigkey 掃描時(shí),Redis 的 OPS 會(huì)突增,為了降低掃描過程中對(duì) Redis 的影響,最好控制一下掃描的頻率,指定 -i 參數(shù)即可,它表示掃描過程中每次掃描后休息的時(shí)間間隔,單位是秒
- 掃描結(jié)果中,對(duì)于容器類型(List、Hash、Set、ZSet)的 key,只能掃描出元素最多的 key。但一個(gè) key 的元素多,不一定表示占用內(nèi)存也多,你還需要根據(jù)業(yè)務(wù)情況,進(jìn)一步評(píng)估內(nèi)存占用情況
集中過期
集中過期產(chǎn)生的慢查詢很容易被忽略,可能我們?cè)跇I(yè)務(wù)上線時(shí),并沒有發(fā)生慢查詢,而是業(yè)務(wù)運(yùn)行時(shí)在某個(gè)時(shí)間點(diǎn)總是突然發(fā)生慢查詢。為什么集中過期會(huì)導(dǎo)致慢查詢呢?我們首先了解下redis的兩種過期策略:
- 被動(dòng)過期:只有當(dāng)訪問某個(gè)key時(shí),才會(huì)檢測該key是否已經(jīng)過期,如果已經(jīng)過期則從實(shí)例刪除該key。
- 主動(dòng)過期:redis內(nèi)部存在一個(gè)定時(shí)任務(wù),默認(rèn)每間隔100毫秒就會(huì)從全局的過期哈希表里面隨機(jī)取出20個(gè)key,然后刪除其中過期的 key,如果過期 key 的比例超過了 25%,則繼續(xù)重復(fù)此過程,直到過期 key 的比例下降到 25% 以下,或者這次任務(wù)的執(zhí)行耗時(shí)超過了 25 毫秒,才會(huì)退出循環(huán)。
值得注意的是,主動(dòng)過期key的定時(shí)任務(wù)是在redis主線程種執(zhí)行的,也就是說如果在執(zhí)行主動(dòng)過期的過程中,出現(xiàn)了集中過期,那就需要大量刪除過期 key ,那么此時(shí)應(yīng)用程序在訪問 Redis 時(shí),必須要等待這個(gè)過期任務(wù)執(zhí)行結(jié)束,Redis 才可以服務(wù)這個(gè)客戶端請(qǐng)求,此時(shí)應(yīng)用訪問 Redis 就可能產(chǎn)生查詢。
如果此時(shí)需要過期刪除的是一個(gè) bigkey,那么這個(gè)耗時(shí)會(huì)更久。而且,這個(gè)操作延遲的命令并不會(huì)記錄在慢日志中。
因?yàn)槁罩局兄?strong>記錄一個(gè)命令真正操作內(nèi)存數(shù)據(jù)的耗時(shí),而 Redis 主動(dòng)刪除過期 key 的邏輯,是在命令真正執(zhí)行之前執(zhí)行的。
對(duì)于集中過期問題,有以下建議
- 避免集中過期,比如將過期時(shí)間隨機(jī)化,添加一個(gè)隨機(jī)的值,分散集中過期的key的過期時(shí)間,降低 Redis 清理過期 key 的壓力
- 對(duì)于Redis 是 4.0 以上版本,可以開啟 lazy-free 機(jī)制,當(dāng)刪除過期 key 時(shí),把釋放內(nèi)存的操作放到后臺(tái)線程中執(zhí)行,避免阻塞主線程
總結(jié)
到此這篇關(guān)于Redis慢查詢的具體使用的文章就介紹到這了,更多相關(guān)Redis慢查詢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用高斯Redis實(shí)現(xiàn)二級(jí)索引的方法
本文介紹了如何通過高斯Redis搭建二級(jí)索引,二級(jí)索引在電商、圖(hexastore)、游戲等領(lǐng)域具有廣泛的應(yīng)用場景,高斯redis現(xiàn)網(wǎng)亦有很多類似應(yīng)用,需要的朋友跟隨小編一起看看吧2022-07-07聊一聊redis奇葩數(shù)據(jù)類型與集群知識(shí)
現(xiàn)在越來越多的項(xiàng)目都會(huì)利用到redis,多實(shí)例redis服務(wù)比單實(shí)例要復(fù)雜的多,這里面涉及到定位、容錯(cuò)、擴(kuò)容等技術(shù)問題,下面這篇文章主要給大家介紹了關(guān)于redis奇葩數(shù)據(jù)類型與集群知識(shí)的相關(guān)資料,需要的朋友可以參考下2022-01-01Redis+aop實(shí)現(xiàn)接口防刷(冪等)的解決方案
在高并發(fā)場景下,可能會(huì)因?yàn)榫W(wǎng)絡(luò)或者服務(wù)器原因,造成延遲,同時(shí)就是有可能會(huì)有人用腳本大量訪問你的接口,造成資源崩潰,所以本文給大家介紹了Redis+aop實(shí)現(xiàn)接口防刷(冪等)的解決方案,需要的朋友可以參考下2024-03-03Redis 的過期策略與鍵的過期時(shí)間設(shè)置方法
Redis通過惰性刪除和定期刪除策略管理內(nèi)存,提供多種命令設(shè)置鍵的過期時(shí)間,并通過過期字典高效處理過期鍵,合理設(shè)置過期時(shí)間、監(jiān)控過期鍵數(shù)量和避免大量鍵同時(shí)過期是最佳實(shí)踐,本文介紹Redis 的過期策略與鍵的過期時(shí)間設(shè)置,感興趣的朋友一起看看吧2025-03-03