網(wǎng)站首頁(yè) 編程語(yǔ)言 正文
Redis 性能影響 - 異步機(jī)制和響應(yīng)延遲
- 一. 異步機(jī)制
- 1.1 Redis 阻塞點(diǎn)
- 1.2 Redis 異步子線程優(yōu)化機(jī)制
- 1.3 惰性刪除 lazy-free
- 二. 如何應(yīng)對(duì) Redis 變慢的情況
- 2.1 確定慢的原因是否在于Redis自身
- 2.2 Redis自身操作特性的影響
- 2.2.1 是否由大量慢查詢命令導(dǎo)致的慢
- 2.2.2 檢查 Redis 對(duì)過(guò)期 key 的操作策略
- 2.2.3 scan命令相關(guān)問(wèn)題
- 2.3 文件系統(tǒng)的影響
- 2.4 操作系統(tǒng)的影響
- 2.5 總結(jié) ☆
一. 異步機(jī)制
首先,我們來(lái)看下Redis
實(shí)例在運(yùn)行的時(shí)候,可能發(fā)生交互的幾個(gè)角色,以及他們主要做了哪些事情:
-
客戶端:網(wǎng)絡(luò)
IO
、鍵值對(duì)的增刪改查API
調(diào)用、數(shù)據(jù)庫(kù)操作。 -
磁盤:生成
RDB
快照、AOF
日志記錄、AOF
日志重寫。 -
主從節(jié)點(diǎn):主庫(kù)生成和傳輸
RDB
文件、從庫(kù)接收RDB
文件、從庫(kù)數(shù)據(jù)庫(kù)清空、從庫(kù)RDB
加載。 - 切片集群實(shí)例:向其他實(shí)例傳輸哈希槽信息、數(shù)據(jù)遷移。
1.1 Redis 阻塞點(diǎn)
首先是第一點(diǎn),和客戶端進(jìn)行交互:
- 我們知道
Redis
中使用了IO多路復(fù)用機(jī)制,避免了主線程一直處于等待網(wǎng)絡(luò)連接的狀態(tài),因此網(wǎng)絡(luò)IO
并不是導(dǎo)致Redis
阻塞的主要因素。 - 主要在于
Redis
底層數(shù)據(jù)操作時(shí)的時(shí)間復(fù)雜度。例如一個(gè)簡(jiǎn)單的Hash
鍵值對(duì)查找,只用O(1)
的時(shí)間復(fù)雜度。但是一旦涉及到范圍查找,全量查找,集合差并集等操作,那么操作的時(shí)間復(fù)雜度就是O(N)
了。 - 此外
bigkey
的刪除和內(nèi)存的申請(qǐng)分配,這個(gè)過(guò)程也是非常耗時(shí)的。那么自然而然的,對(duì)于Redis
實(shí)例中所有鍵值對(duì)的清除操作,即flushdb
操作,也是導(dǎo)致Redis
阻塞的一個(gè)點(diǎn)。
備注:內(nèi)存釋放流程。
釋放內(nèi)存的時(shí)候,操作系統(tǒng)先將釋放掉的內(nèi)存塊插入一個(gè)空閑內(nèi)存塊鏈表,以便后續(xù)進(jìn)行內(nèi)存的管理和再分配。這個(gè)果子會(huì)阻塞當(dāng)前釋放內(nèi)存的應(yīng)用程序。
bigkey
刪除的測(cè)試以及對(duì)應(yīng)消耗的時(shí)間(來(lái)源 Redis 核心技術(shù)與實(shí)戰(zhàn))
第二點(diǎn):和磁盤交互:
- 這一塊主要是和
AOF
的日志操作有關(guān)。AOF
同步在always
策略下寫回磁盤的這個(gè)過(guò)程會(huì)阻塞主線程。而生成RBD
快照以及AOF
的重寫操作都是交給子進(jìn)程來(lái)完成的,不影響主進(jìn)程。具體可以在復(fù)習(xí)下AOF 寫回策略。
第三點(diǎn):和主從節(jié)點(diǎn)交互:
- 主從集群中,主庫(kù)主要是生成
RDB
文件,并傳輸給從庫(kù)。雖然創(chuàng)建和傳輸RDB
文件都是由子進(jìn)程來(lái)完成的。但是fork
子進(jìn)程的這個(gè)過(guò)程會(huì)阻塞。阻塞的時(shí)間取決于拷貝的內(nèi)存大小,實(shí)例越大,內(nèi)存頁(yè)表越大,fork
時(shí)間也就越久。同樣可以復(fù)習(xí)下AOF 寫回策略。 - 從庫(kù)在接收完
RDB
文件后,首先會(huì)清除自身的數(shù)據(jù),即flushdb
操作,這個(gè)過(guò)程會(huì)阻塞,上文有提及。而加載RDB
的過(guò)程中,從庫(kù)也會(huì)阻塞。
第四點(diǎn):和切片集群實(shí)例交互:
- 首先,
Redis
集群中,哈希槽的信息會(huì)在實(shí)例之間相互傳遞,而數(shù)據(jù)遷移是漸進(jìn)式執(zhí)行,因此對(duì)于Redis
的阻塞影響不大。 - 倘若遷移了
bigkey
,此時(shí)就會(huì)造成主進(jìn)程的阻塞。
阻塞點(diǎn)總結(jié)下就是:
- 集合范圍查找或者聚合操作。對(duì)于客戶端而言,需要得到其結(jié)果。
-
bigkey
的刪除、創(chuàng)建。遷移bigkey
。對(duì)于客戶端而言,無(wú)需返回結(jié)果。 - 清空數(shù)據(jù)庫(kù)操作。對(duì)于客戶端而言,無(wú)需返回結(jié)果。
-
AOF
日志同步寫回磁盤操作。對(duì)于客戶端而言,無(wú)需返回結(jié)果。 - 從庫(kù)加載
RDB
文件。對(duì)于客戶端而言,需要其加載完畢才能使用。
1.2 Redis 異步子線程優(yōu)化機(jī)制
針對(duì)上述總結(jié),Redis
主要針對(duì)三個(gè)點(diǎn)去做了異步優(yōu)化:
-
Redis
主線程啟動(dòng)的時(shí)候,就會(huì)調(diào)用操作系統(tǒng)提供的pthread_create
函數(shù)去創(chuàng)建3個(gè)子進(jìn)程,分別負(fù)責(zé)bigkey
刪除、數(shù)據(jù)庫(kù)清除、AOF
日志同步寫。 -
主線程通過(guò)一個(gè)任務(wù)隊(duì)列和子進(jìn)程進(jìn)行交互。以刪除操作為例,會(huì)將對(duì)應(yīng)的操作封裝成一個(gè)任務(wù),放到隊(duì)列里面,然后給客戶端返回信息表明刪除完成。(這里實(shí)際上數(shù)據(jù)并未被刪除,需要等待子進(jìn)程去執(zhí)行真正的內(nèi)存釋放操作)即惰性刪除
lazy free
。
除此之外,Redis4.0
之后還提供另外的兩個(gè)功能,用于異步的鍵值對(duì)刪除和數(shù)據(jù)庫(kù)清除工作:
- 鍵值對(duì)刪除:對(duì)于集合類型的
bigkey
,建議使用unlink
命令。 - 數(shù)據(jù)庫(kù)清空:可以再
flushdb
命令后面跟著async
選項(xiàng),既可以讓子線程在后臺(tái)異步清空數(shù)據(jù)庫(kù)。即flushdb async
。 - 倘若是4.0版本前的,可以通過(guò)
scan
命令先讀取數(shù)據(jù),在進(jìn)行刪除。這一部分建議使用pipeline
,因?yàn)闆](méi)有批量刪除的相關(guān)API
,只能一條一條刪除。
Redis
中Pipeline
是什么東西?
首先,常規(guī)的來(lái)說(shuō),我們客戶端和Redis
實(shí)例進(jìn)行交互的時(shí)候,模式就是這樣的:響應(yīng)-->請(qǐng)求,響應(yīng)-->請(qǐng)求,響應(yīng)-->請(qǐng)求
。3次來(lái)回。
而管道Pipeline
的作用就是將上述的模式改為:響應(yīng),響應(yīng),響應(yīng)-->請(qǐng)求,請(qǐng)求,請(qǐng)求
。1次來(lái)回。
這里以Jedis
的使用為例(也有Spring
整合Redis
,使用redisTemplate
的情況)
@Test
public void testPipelined() {
Pipeline pipelined = jedis.pipelined();
for (int i = 0; i < 10; i++) {
pipelined.hset("testPipelined", "testId_" + i, String.valueOf(i));
}
List<Object> objects = pipelined.syncAndReturnAll();
System.out.println(objects);
}
結(jié)果如下:
1.3 惰性刪除 lazy-free
惰性刪除 lazy-free
是Redis4.0
新增的功能,默認(rèn)關(guān)閉,需要手動(dòng)開(kāi)啟。有這么幾個(gè)相關(guān)的配置項(xiàng):
-
lazyfree-lazy-expire
:key
在過(guò)期刪除時(shí)嘗試異步釋放內(nèi)存。 -
lazyfree-lazy-eviction
:內(nèi)存達(dá)到maxmemory
并設(shè)置了淘汰策略時(shí)嘗試異步釋放內(nèi)存。 -
lazyfree-lazy-server-del
:執(zhí)行rename、move
等命令或需要覆蓋一個(gè)key
時(shí),刪除舊key
嘗試異步釋放內(nèi)存。 -
replica-lazy-flush
:主從全量同步,從庫(kù)清空數(shù)據(jù)庫(kù)時(shí)異步釋放內(nèi)存。
注意:在開(kāi)啟了lazy-free
的情況下,需要使用unlink
命令才有可能異步刪除key
,使用del
依舊是同步刪除。
上面4個(gè)相關(guān)配置中,除了最后一點(diǎn),其他的異步策略都是可能發(fā)生的。這和key
的類型、編碼方式以及元素?cái)?shù)量有關(guān)。只有在以下幾種情況下,Redis
才會(huì)開(kāi)啟異步內(nèi)存釋放:
-
Hash/Set
類型的Key
:底層采用哈希表存儲(chǔ)并且元素?cái)?shù)量超過(guò)64個(gè)的時(shí)候,Redis - 數(shù)據(jù)結(jié)構(gòu)和持久化機(jī)制。 -
ZSet
類型的Key
:底層采用跳表存儲(chǔ),并且元素?cái)?shù)量超過(guò)64個(gè)的時(shí)候。 -
List
類型的Key
:鏈表節(jié)點(diǎn)數(shù)量超過(guò)64個(gè)。(此處并非元素?cái)?shù)量,每個(gè)節(jié)點(diǎn)可能有多個(gè)元素)
集合類型比較特殊,但是相對(duì)而言比較常見(jiàn)的就是String
類型的,可見(jiàn),String
類型的鍵值對(duì),不管其占用內(nèi)存有多大,都是在主線程上完成內(nèi)存釋放操作的,所以,如果bigkey
越大,那么主線程阻塞的時(shí)間也就越久。
最后再說(shuō)下scan
跟keys
相比有什么優(yōu)劣勢(shì):
- 首先
scan
和keys
命令都是通配查找,時(shí)間復(fù)雜度都是O(N)
。 - 但是
scan
命令可以不用阻塞主線程,keys
命令是阻塞的。 -
scan
命令需要進(jìn)行迭代多次返回,根據(jù)游標(biāo)來(lái)。同時(shí)返回的數(shù)據(jù)可能有重復(fù)。
scan
命令的Java
使用案例:
@Test
public void testScan() {
Pipeline pipelined = jedis.pipelined();
for (int i = 0; i < 10; i++) {
pipelined.set("key:" + i, "value_" + i);
}
pipelined.sync();
// 游標(biāo)初始值為0
String cursor = ScanParams.SCAN_POINTER_START;
ScanParams scanParams = new ScanParams();
// 模糊匹配
scanParams.match("key:*");
scanParams.count(3);
while (true) {
ScanResult<String> scanResult = jedis.scan(cursor, scanParams);
List<String> result = scanResult.getResult();
cursor = scanResult.getCursor();
System.out.println("當(dāng)前獲取結(jié)果:" + result + " 拿到的游標(biāo)值:" + cursor);
if ("0".equals(cursor)) {
break;
}
}
}
結(jié)果如下:
二. 如何應(yīng)對(duì) Redis 變慢的情況
我們看下下面的架構(gòu)圖,紅色的三個(gè)部分是影響Redis
性能的三大因素:
-
Redis
自身的操作特性。 - 文件系統(tǒng)。
- 操作系統(tǒng)。
2.1 確定慢的原因是否在于Redis自身
首先,我們應(yīng)該去確認(rèn)變慢的原因是否在于Redis
本身。即查看Redis
的響應(yīng)延遲有多少。
通過(guò)以下命令即可:
./redis-cli --latency -h host -p port
結(jié)果如下:
或者是基于當(dāng)前的Redis
實(shí)例環(huán)境做基線性能判斷:系統(tǒng)在低壓力、無(wú)干擾下的基本性能。
# 打印120秒內(nèi)檢測(cè)到的最大延遲。
./redis-cli --intrinsic-latency 120
結(jié)果如下:會(huì)階段性的打印 截止當(dāng)前時(shí)刻最久的響應(yīng)時(shí)長(zhǎng)。
以上兩種情況給出的數(shù)據(jù)都是僅供參考,因?yàn)?code>Redis如果變慢了,真正的原因是需要具體分析的。
2.2 Redis自身操作特性的影響
這一塊主要涉及到兩點(diǎn):
- 慢查詢命令。
- 過(guò)期
key
操作。
2.2.1 是否由大量慢查詢命令導(dǎo)致的慢
首先需要確定這一點(diǎn),是否存在大量的慢查詢命令,再去解決。主要通過(guò)慢查詢?nèi)罩緛?lái)查看。首先慢查詢?nèi)罩居袔讉€(gè)相關(guān)的配置項(xiàng):
-
slowlog-log-slower-than
:慢查詢?nèi)罩镜臅r(shí)間閾值,單位微妙,默認(rèn)10000微妙。
值為0:所有命令都記錄到慢日志中。
值為負(fù)數(shù):禁止使用慢查詢?nèi)罩尽?/p> -
slowlog-max-len
:慢查詢?nèi)罩鹃L(zhǎng)度,默認(rèn)128。當(dāng)日志滿了的時(shí)候,最老的一條記錄將會(huì)被刪除。
可以通過(guò)以下命令臨時(shí)配置(redis.conf
文件上編輯才是永久生效):
config set slowlog-log-slower-than 0
config set slowlog-max-len 10
使用命令查看慢查詢?nèi)罩?,?nèi)容如下:
倘若通過(guò)慢查詢?nèi)罩景l(fā)現(xiàn),確實(shí)存在大量的慢查詢?nèi)罩?,那么可以開(kāi)始做對(duì)應(yīng)的處理了:
- 第一種情形:用其他高效命令代替。例如使用
sscan
命令替代smembers
命令(獲取某個(gè)集合中的所有數(shù)據(jù)),避免一次性返回大量數(shù)據(jù),造成線程阻塞。 - 第二種情形:倘若業(yè)務(wù)上涉及到了集合的交并集操作(數(shù)據(jù)量龐大的情況下),可以讓其在客戶端完成,不在
Redis
上操作。
2.2.2 檢查 Redis 對(duì)過(guò)期 key 的操作策略
Redis
中對(duì)過(guò)期key
有著專門的自動(dòng)刪除機(jī)制,默認(rèn)情況下具體流程如下:
- Redis中有個(gè)配置項(xiàng)
ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP
,默認(rèn)值為20。這里簡(jiǎn)稱為M
。首先Redis
每100毫秒
就會(huì)采樣M
個(gè)key
,并將其中過(guò)期的key
全部刪除。 - 倘若剩余的
key
中,有超過(guò)25%
的key
依舊是過(guò)期的,那么重復(fù)刪除的過(guò)程,直到過(guò)期key
的比例降低至25%
以下。 - 也因此,一般情況下,每秒鐘會(huì)刪除200個(gè)
key
。
問(wèn)題在于:Redis
刪除過(guò)期key
,釋放其內(nèi)存空間的這一個(gè)動(dòng)作是阻塞的。倘若在同一時(shí)間內(nèi),有大量的key同時(shí)過(guò)期,就會(huì)造成Redis不斷的去執(zhí)行刪除操作,從而導(dǎo)致主線程的阻塞。
當(dāng)然,Redis4.0
之后是可以對(duì)這個(gè)問(wèn)題進(jìn)行優(yōu)化的??梢詮?fù)習(xí)下1.2小節(jié)的內(nèi)容。解決方案如下:
- 首先同一時(shí)間內(nèi)大量
key
過(guò)期(有點(diǎn)緩存雪崩的味兒了昂),我們只需要在業(yè)務(wù)代碼中,往Redis
中插入數(shù)據(jù)的時(shí)候,盡量給key
通過(guò)EXPIREAT
命令設(shè)置不同的過(guò)期秒數(shù)。 - 倘若某一部分?jǐn)?shù)據(jù),對(duì)這部分?jǐn)?shù)據(jù)的過(guò)期時(shí)間要求比較高,可以加上一個(gè)一定大小范圍內(nèi)的隨機(jī)數(shù)。這樣,既保證了
key
在一個(gè)鄰近時(shí)間范圍內(nèi)被刪除,又避免了同時(shí)過(guò)期造成的壓力。
2.2.3 scan命令相關(guān)問(wèn)題
上文提到過(guò),使用scan
命令返回的數(shù)據(jù)可能有重復(fù)。除此之外,對(duì)scan
命令問(wèn)的最多的就是是否會(huì)漏掉key
。那么這里做個(gè)解釋。
首先請(qǐng)讀者了解Redis
的rehash
機(jī)制(還沒(méi)聽(tīng)過(guò)的點(diǎn)這里Redis - 數(shù)據(jù)結(jié)構(gòu)和持久化機(jī)制).
scan
命令不會(huì)漏key
的原因:
-
Redis
在Scan
遍歷全局哈希表的時(shí)候,是采用高位進(jìn)位法
的方式遍歷的。 - 哈希表擴(kuò)容的時(shí)候,會(huì)將舊哈希表中的數(shù)據(jù)映射到新哈希表。同時(shí)保留原來(lái)的先后順序。
- 這樣就保證遍歷的時(shí)候不會(huì)遺漏也不會(huì)重復(fù)。
scan
命令得到重復(fù)key
的原因:(在哈希表縮容情況下)
- 遍歷過(guò)的哈希桶在縮容的時(shí)候,會(huì)映射到新哈希表中沒(méi)有遍歷到的位置。
- 因此繼續(xù)遍歷新哈希表的時(shí)候,會(huì)對(duì)同一個(gè)
key
返回多次。
值得注意的一點(diǎn)是,在上文中有涉及到scan
命令的使用,其中還有個(gè)count
的設(shè)置,其意思就是每次查詢返回的key
數(shù)量不會(huì)超過(guò)count
的值。但是實(shí)際使用的時(shí)候卻可能存在偏差。理由如下:
- 當(dāng)使用
Hash/Set/Sorted Set
這幾種集合去存儲(chǔ)數(shù)據(jù)并且元素?cái)?shù)量比較少時(shí),底層會(huì)采用intset/ziplist
方式存儲(chǔ)(數(shù)組和壓縮列表),如果以這種方式存儲(chǔ),在執(zhí)行HSCAN/SSCAN/ZSCAN
命令時(shí),會(huì)無(wú)視count
參數(shù),直接把所有元素一次性返回。 意思就是此時(shí)得到的元素?cái)?shù)量 >count
值。 - 底層轉(zhuǎn)化為哈希表或者跳表存儲(chǔ)的時(shí)候,才會(huì)真正地使用
count
參數(shù)。作為返回個(gè)數(shù)的上限。
2.3 文件系統(tǒng)的影響
Redis
的性能也受其文件系統(tǒng)影響。最主要的就是AOF
日志。我們知道,AOF
日志有三種寫回策略:no、everysec。always
。而它們依賴于文件系統(tǒng)的兩個(gè)操作調(diào)用來(lái)完成:
-
write
:只需要將日志記錄到內(nèi)核緩沖區(qū)中,就可以返回。 -
fsync
:主要負(fù)責(zé)將日志寫回到磁盤中,完成之后才可以返回。
然后我們?cè)倩仡櫼幌乱韵聨讉€(gè)知識(shí)點(diǎn):
-
everysec
模式下:Redis
會(huì)使用后臺(tái)子進(jìn)程異步完成fsync
操作。每秒調(diào)用一次。 -
always
模式下:每執(zhí)行一個(gè)操作,就調(diào)用一次fsync
操作。 -
no
模式下:先調(diào)用write
寫日志文件,再由操作系統(tǒng)周期性地將日志寫回磁盤。
針對(duì)上述情況,有這么幾個(gè)阻塞點(diǎn):
-
AOF
日志很大的時(shí)候,會(huì)進(jìn)行AOF
重寫,雖然這個(gè)步驟是由子進(jìn)程來(lái)完成的。但是AOF
重寫會(huì)對(duì)磁盤進(jìn)行大量IO
操作,同時(shí),fsync
又需要等到數(shù)據(jù)寫到磁盤后才能返回,所以,當(dāng)AOF
重寫的壓力比較大時(shí),就會(huì)導(dǎo)致fsync
被阻塞。 - 在執(zhí)行
fsync
的時(shí)候,倘若發(fā)現(xiàn)上一次fsync
操作還沒(méi)有執(zhí)行完畢,就會(huì)阻塞。因此對(duì)于always
模式,倘若后臺(tái)子進(jìn)程執(zhí)行fsync
操作比較頻繁,主線程也會(huì)隨之受到影響。
總的來(lái)說(shuō)就是:AOF
日志文件太大 以及 fsync
操作比較頻繁。會(huì)影響主線程的性能。
那么接下來(lái)就是如何去改善這個(gè)情況。
-
首先,根據(jù)你自身的業(yè)務(wù)來(lái)判斷,
Redis
中的數(shù)據(jù)可靠性級(jí)別應(yīng)該是哪種?如果Redis
僅僅是當(dāng)做一個(gè)緩存的作用,那么是不是可以排查下寫回策略是否配置了always
? -
如果對(duì)延遲十分敏感,可以嘗試配置
no-appendfsync-on-rewrite = yes;
該選項(xiàng)會(huì)在AOF
重寫期間避免調(diào)用fsync
,而是將數(shù)據(jù)暫存在內(nèi)存中就返回。
2.4 操作系統(tǒng)的影響
操作系統(tǒng)這里有一個(gè)潛在的瓶頸:操作系統(tǒng)內(nèi)存的swap
部分。
- 正常情況下,
Redis
的操作是在內(nèi)存上進(jìn)行的。 -
倘若機(jī)器內(nèi)存不夠,一旦
swap
被觸發(fā)了,Redis
的請(qǐng)求操作需要等到磁盤數(shù)據(jù)讀寫完成才行,swap
觸發(fā)后影響的是Redis
主線程,這會(huì)極大地增加Redis
的響應(yīng)時(shí)間。
由于觸發(fā)swap
機(jī)制的主要原因是機(jī)器的物理內(nèi)存不足,因此可以參考以下幾種方案去解決:
- 增加
Redis
實(shí)例所在的機(jī)器內(nèi)存。 - 使用
Redis
集群,把壓力分?jǐn)傞_(kāi)來(lái)。
另外的一個(gè)細(xì)節(jié)點(diǎn)就是:Linux
系統(tǒng)的內(nèi)存大頁(yè)機(jī)制(THP
)
總的來(lái)說(shuō)就是該機(jī)制支持2MB
大小的內(nèi)存頁(yè)的分配。而常規(guī)來(lái)說(shuō)的內(nèi)存頁(yè)分配維度是4KB
。
我們知道,Redis
利用了寫時(shí)復(fù)制技術(shù)(可以點(diǎn)擊這里復(fù)習(xí)),在執(zhí)行快照的同時(shí),正常處理寫操作。總的來(lái)說(shuō)就是將數(shù)據(jù)拷貝一份。 那么在這個(gè)背景下,倘若開(kāi)啟了內(nèi)存大頁(yè)機(jī)制,會(huì)有什么影響?
- 如果采用了內(nèi)存大頁(yè),那么,即使客戶端請(qǐng)求只修改
1KB
的數(shù)據(jù),Redis
也需要拷貝2MB
的大頁(yè). - 如果是常規(guī)內(nèi)存頁(yè)機(jī)制,只用拷貝
4KB
。 - 當(dāng)客戶端請(qǐng)求修改或新寫入數(shù)據(jù)較多時(shí),內(nèi)存大頁(yè)機(jī)制將導(dǎo)致大量的拷貝,這就會(huì)影響
Redis
正常的訪存操作,最終導(dǎo)致性能變慢。
內(nèi)存大頁(yè)機(jī)制查看是否開(kāi)啟:
cat /sys/kernel/mm/transparent_hugepage/enabled
結(jié)果如下:
關(guān)閉:
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag
echo 'echo never > /sys/kernel/mm/transparent_hugepage/defrag' >> /etc/rc.d/rc.local??
echo 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' >> /etc/rc.d/rc.local??
grep Huge /proc/meminfo
cat /proc/sys/vm/nr_hugepages
結(jié)果如下:
2.5 總結(jié) ☆
上文說(shuō)了不少,那么在發(fā)現(xiàn)Redis
變慢的時(shí)候,可以按照以下幾個(gè)步驟來(lái)排查問(wèn)題。
1.使用slowlog
查看是否存在一些復(fù)雜度比較高或全量查詢的命令(sort,suion
等)。
解決:
- 用分批查詢替代全量查詢。
- 復(fù)雜命令可以放到客戶端做。
2.排查bigkey
。
./redis-cli --bigkeys -a 你的Redis密碼
結(jié)果如下:
這時(shí)候就可以優(yōu)化業(yè)務(wù)了,避免存儲(chǔ)bigkey
。倘若Redis
版本在4.0以后,可以開(kāi)啟lazy-free
機(jī)制。
3.給key
增加一個(gè)隨機(jī)的過(guò)期時(shí)間。避免大量key
集中過(guò)期。
4.倘若業(yè)務(wù)上不需要數(shù)據(jù)的高可靠,那么可以視情況而定修改回寫策略。always
模式下,對(duì)Redis
的性能影響比較大。比如可以改成everysec
模式,并且對(duì)于數(shù)據(jù)丟失不敏感的業(yè)務(wù)可以關(guān)閉AOF
。
5.避免操作系統(tǒng)開(kāi)啟swap
,可以適當(dāng)調(diào)大Redis
實(shí)例內(nèi)存。或者部署Redis
集群。
6.關(guān)閉透明大頁(yè)機(jī)制。
原文鏈接:https://blog.csdn.net/Zong_0915/article/details/126235291
相關(guān)推薦
- 2023-02-17 C++中二叉堆排序詳解_C 語(yǔ)言
- 2022-08-26 Redis哨兵模式實(shí)現(xiàn)一主二從三哨兵_Redis
- 2022-06-18 datagridview實(shí)現(xiàn)手動(dòng)添加行數(shù)據(jù)_C#教程
- 2022-02-09 C++解決輸出鏈表中倒數(shù)k個(gè)結(jié)點(diǎn)的問(wèn)題_C 語(yǔ)言
- 2023-01-28 Flask框架運(yùn)用Axios庫(kù)實(shí)現(xiàn)前后端交互詳解_python
- 2023-05-10 Numpy中np.dot與np.matmul的區(qū)別詳解_python
- 2021-12-04 C#獲取Windows10屏幕縮放比例的操作方法_C#教程
- 2022-06-17 Ruby3多線程并行Ractor使用方法詳解_ruby專題
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲(chǔ)小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過(guò)濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡(jiǎn)單動(dòng)態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對(duì)象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支