日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學(xué)無(wú)先后,達(dá)者為師

網(wǎng)站首頁(yè) 編程語(yǔ)言 正文

Redis 性能影響 - 異步機(jī)制和響應(yīng)延遲

作者:Zong_0915 更新時(shí)間: 2022-08-13 編程語(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):和磁盤交互:

  1. 這一塊主要是和AOF的日志操作有關(guān)。AOF同步在always策略下寫回磁盤的這個(gè)過(guò)程會(huì)阻塞主線程。而生成RBD快照以及AOF的重寫操作都是交給子進(jìn)程來(lái)完成的,不影響主進(jìn)程。具體可以在復(fù)習(xí)下AOF 寫回策略。

第三點(diǎn):和主從節(jié)點(diǎn)交互:

  1. 主從集群中,主庫(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 寫回策略。
  2. 從庫(kù)在接收完RDB文件后,首先會(huì)清除自身的數(shù)據(jù),即flushdb操作,這個(gè)過(guò)程會(huì)阻塞,上文有提及。而加載RDB的過(guò)程中,從庫(kù)也會(huì)阻塞。

第四點(diǎn):和切片集群實(shí)例交互:

  1. 首先,Redis集群中,哈希槽的信息會(huì)在實(shí)例之間相互傳遞,而數(shù)據(jù)遷移是漸進(jìn)式執(zhí)行,因此對(duì)于Redis的阻塞影響不大。
  2. 倘若遷移了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)化:

  1. 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日志同步寫。
  2. 主線程通過(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,只能一條一條刪除。

RedisPipeline是什么東西?

首先,常規(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-freeRedis4.0新增的功能,默認(rèn)關(guān)閉,需要手動(dòng)開(kāi)啟。有這么幾個(gè)相關(guān)的配置項(xiàng):

  • lazyfree-lazy-expirekey在過(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ō)下scankeys相比有什么優(yōu)劣勢(shì):

  1. 首先scankeys命令都是通配查找,時(shí)間復(fù)雜度都是O(N)。
  2. 但是scan命令可以不用阻塞主線程,keys命令是阻塞的。
  3. 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)的處理了:

  1. 第一種情形:用其他高效命令代替。例如使用sscan命令替代smembers命令(獲取某個(gè)集合中的所有數(shù)據(jù)),避免一次性返回大量數(shù)據(jù),造成線程阻塞。
  2. 第二種情形:倘若業(yè)務(wù)上涉及到了集合的交并集操作(數(shù)據(jù)量龐大的情況下),可以讓其在客戶端完成,不在Redis上操作。

2.2.2 檢查 Redis 對(duì)過(guò)期 key 的操作策略

Redis中對(duì)過(guò)期key有著專門的自動(dòng)刪除機(jī)制,默認(rèn)情況下具體流程如下:

  1. Redis中有個(gè)配置項(xiàng)ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP,默認(rèn)值為20。這里簡(jiǎn)稱為M。首先Redis100毫秒就會(huì)采樣M個(gè)key,并將其中過(guò)期的key全部刪除。
  2. 倘若剩余的key中,有超過(guò)25%key依舊是過(guò)期的,那么重復(fù)刪除的過(guò)程,直到過(guò)期key的比例降低至25%以下。
  3. 也因此,一般情況下,每秒鐘會(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)容。解決方案如下:

  1. 首先同一時(shí)間內(nèi)大量key過(guò)期(有點(diǎn)緩存雪崩的味兒了昂),我們只需要在業(yè)務(wù)代碼中,往Redis中插入數(shù)據(jù)的時(shí)候,盡量給key通過(guò)EXPIREAT命令設(shè)置不同的過(guò)期秒數(shù)。
  2. 倘若某一部分?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)讀者了解Redisrehash機(jī)制(還沒(méi)聽(tīng)過(guò)的點(diǎn)這里Redis - 數(shù)據(jù)結(jié)構(gòu)和持久化機(jī)制).

scan命令不會(huì)漏key的原因:

  1. RedisScan遍歷全局哈希表的時(shí)候,是采用 高位進(jìn)位法 的方式遍歷的。
  2. 哈希表擴(kuò)容的時(shí)候,會(huì)將舊哈希表中的數(shù)據(jù)映射到新哈希表。同時(shí)保留原來(lái)的先后順序。
  3. 這樣就保證遍歷的時(shí)候不會(huì)遺漏也不會(huì)重復(fù)。

scan命令得到重復(fù)key的原因:(在哈希表縮容情況下)

  1. 遍歷過(guò)的哈希桶在縮容的時(shí)候,會(huì)映射到新哈希表中沒(méi)有遍歷到的位置。
  2. 因此繼續(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部分。

  1. 正常情況下,Redis 的操作是在內(nèi)存上進(jìn)行的。
  2. 倘若機(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等)。

解決:

  1. 用分批查詢替代全量查詢。
  2. 復(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

欄目分類
最近更新