日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

redis核心技术与实战(三) 性能篇

發(fā)布時間:2025/3/8 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 redis核心技术与实战(三) 性能篇 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

影響redis性能主要有以下部分:
Redis 內(nèi)部的阻塞式操作;
CPU核和NUMA架構(gòu)
Redis關(guān)鍵系統(tǒng)配置
Redis內(nèi)存碎片
Redis緩沖區(qū)


下面一個個來介紹這些地方

1.《redis 有哪些阻塞點?》
redis實例主要交互的對象有以下幾點,我們依據(jù)下面這些點看看redis有哪些阻塞操作:

客戶端交互:網(wǎng)絡(luò)IO,增刪改查,數(shù)據(jù)庫操作
磁盤交互: AOF 同步磁盤,AOF重寫,RDB模式持久化
從庫交互: 數(shù)據(jù)同步,RDB文件生成,RDB文件傳輸,清空數(shù)據(jù)庫, 從庫加載RDB文件
切片集群交互:向其他實例傳輸哈希槽信息,數(shù)據(jù)遷移。
1. reids阻塞點分析
1.客戶端交互
a. redis實例與客戶端網(wǎng)絡(luò)IO交互會阻塞redis嗎?

多個客戶端 可以同時與 redis 交互,競爭redis 資源, 由于redis 使用了IO多路復(fù)用的線程模式,使redis 不會等待阻塞在某一個客戶端,不響應(yīng)與其他客戶端 的交互,所以 redis與客戶端的 IO 操作 不是 阻塞點;

b. 讀寫操作

集合元素全量查詢操作 HGETALL、SMEMBERS,以及集合的聚合統(tǒng)計操作,例如求交、并和差集。

這些操作往往時間復(fù)雜度是O(n),所以這是

另外,大量數(shù)據(jù)刪除操作,也是redis 的另一個阻塞點;

因為 redis刪除操作涉及 內(nèi)存空間的釋放和管理,釋放內(nèi)存只是redis的第一步,為了更好的管理規(guī)劃內(nèi)存空間,在釋放內(nèi)存時,操作系統(tǒng)會維護一個內(nèi)存塊鏈表,把釋放的內(nèi)存空間插入空閑的內(nèi)存塊鏈表,以便后續(xù)管理使用;

當(dāng)有大量內(nèi)存被釋放時,空閑的內(nèi)存塊鏈表操作時間就會增加,可能會造成redis主線程的阻塞;

所以,

2.磁盤交互
RDB快照和AOF重寫都 是 redis fork出來的子線程執(zhí)行的,只會在fork子線程的時候阻塞主線程, RDB和AOF重寫都不會造成阻塞;

但是,redis AOF模式下 有三種同步落盤操作:NO,every seconds , 同步寫日志;

NO,every seconds 都是異步執(zhí)行的 ,同步寫日志比較特殊,不靠異步子線程完成

一個同步寫磁盤的操作的耗時大約是 1~2ms,當(dāng)有大量寫操作記錄在AOF日志時,并要求同步寫回的話,就會阻塞主線程;

所以,

3.主從交互
生成RDB文件,RDB文件傳輸都是 redis子線程來完成的,不阻塞;

對于從庫來說, 需要主線程 加載RDB文件后,才能執(zhí)行以后的 數(shù)據(jù)同步操作,

所以,

4.切片集群
**數(shù)據(jù)遷移:**當(dāng)我們部署 Redis 切片集群時,每個 Redis 實例上分配的哈希槽信息需要在不同實例間進行傳遞,同時,當(dāng)需要進行負載均衡或者有實例增刪時,數(shù)據(jù)會在不同的實例間進行遷移。不過,哈希槽的信息量不大,而數(shù)據(jù)遷移是漸進式執(zhí)行的,所以,一般來說,這兩類操作對 Redis 主線程的阻塞風(fēng)險不大。

但是,如果你使用了 Redis Cluster 方案,而且同時正好遷移的是 bigkey 的話,就會造成主線程的阻塞,因為 Redis Cluster 使用了同步遷移,所以, Redis Cluster 中 大量bigkey數(shù)據(jù)遷移,可能導(dǎo)致 主線程;

2.關(guān)鍵路徑與非關(guān)鍵路徑
總結(jié)一下,有哪些阻塞點:

集合全量查詢和聚合操作;

bigkey 刪除和清空數(shù)據(jù)庫;

AOF 日志同步寫;

從庫加載 RDB 文件。

redis解決方案:

redis提供異步線程機制,那么以上所有阻塞點都可以用異步執(zhí)行嗎?我們來分析下;

在這之前我們先來看看什么是 關(guān)鍵路徑 ,什么是非關(guān)鍵路徑;

關(guān)鍵路徑: 客戶端需要等待redis返回具體結(jié)果,并根據(jù)結(jié)果做出操作 的是關(guān)鍵路徑,如:讀操作;

非關(guān)鍵路徑:反之,客戶端不關(guān)心 返回結(jié)果,不用給客戶端返回具體數(shù)據(jù)的 操作就是非關(guān)鍵路徑,如:刪除操作;

集合全量查詢和聚合操作: 需要給客戶端返回具體結(jié)果, 關(guān)鍵路徑;

bigkey 刪除和清空數(shù)據(jù)庫: 非關(guān)鍵路徑

AOF 日志同步寫:為了保證數(shù)據(jù)可靠性,Redis 實例需要保證 AOF 日志中的操作記錄已經(jīng)落盤,這個操作雖然需要實例等待,但它并不會返回具體的數(shù)據(jù)結(jié)果給實例。 所以,它是 非關(guān)鍵路徑。

從庫加載 RDB 文件: 庫要想對客戶端提供數(shù)據(jù)存取服務(wù),就必須把 RDB 文件加載完成。 所以,它是關(guān)鍵路徑;

3.redis異步子線程機制
Redis 主線程啟動后,會使用操作系統(tǒng)提供的 pthread_create 函數(shù)創(chuàng)建 3 個子線程,分別由它們負責(zé) AOF 日志寫操作、鍵值對刪除以及文件關(guān)閉的異步執(zhí)行。

主線程通過一個鏈表形式的任務(wù)隊列和子線程進行交互。當(dāng)收到鍵值對刪除和清空數(shù)據(jù)庫的操作時,主線程會把這個操作封裝成一個任務(wù),放入到任務(wù)隊列中,然后給客戶端返回一個完成信息,表明刪除已經(jīng)完成。

但實際上,這個時候刪除還沒有執(zhí)行,等到后臺子線程從任務(wù)隊列中讀取任務(wù)后,才開始實際刪除鍵值對,并釋放相應(yīng)的內(nèi)存空間。因此,我們把這種異步刪除也稱為惰性刪除(lazy free)。此時,刪除或清空操作不會阻塞主線程,這就避免了對主線程的性能影響。

異步子線程機制:

注意點:異步的鍵值對刪除和數(shù)據(jù)庫清空操作是 Redis 4.0 后提供的功能,Redis 也提供了新的命令來執(zhí)行這兩個操作:

鍵值對刪除:當(dāng)你的集合類型中有大量元素(例如有百萬級別或千萬級別元素)需要刪除時,我建議你使用 UNLINK 命令。

清空數(shù)據(jù)庫:可以在 FLUSHDB 和 FLUSHALL 命令后加上 ASYNC 選項,這樣就可以讓后臺子線程異步地清空數(shù)據(jù)庫,如下所示:

FLUSHDB ASYNC
FLUSHALL AYSNC
1
2
4.建議與擴展
1.建議
集合全量查詢和聚合操作:可以使用 SCAN 命令,分批讀取數(shù)據(jù),再在客戶端進行聚合計算;
從庫加載 RDB 文件:把主庫的數(shù)據(jù)量大小控制在 2~4GB 左右,以保證 RDB 文件能以較快的速度加載。
2.擴展
我們今天學(xué)習(xí)了關(guān)鍵路徑上的操作,你覺得,Redis 的寫操作(例如 SET、HSET、SADD 等)是在關(guān)鍵路徑上嗎?

需要客戶端根據(jù)業(yè)務(wù)需要來區(qū)分:

1、如果客戶端依賴操作返回值的不同,進而需要處理不同的業(yè)務(wù)邏輯,那么HSET和SADD操作算關(guān)鍵路徑,而SET操作不算關(guān)鍵路徑。因為HSET和SADD操作,如果field或member不存在時,Redis結(jié)果會返回1,否則返回0。而SET操作返回的結(jié)果都是OK,客戶端不需要關(guān)心結(jié)果有什么不同。

2、如果客戶端不關(guān)心返回值,只關(guān)心數(shù)據(jù)是否寫入成功,那么SET/HSET/SADD不算關(guān)鍵路徑,多次執(zhí)行這些命令都是冪等的,這種情況下可以放到異步線程中執(zhí)行。

3、但是有種例外情況,如果Redis設(shè)置了maxmemory,但是卻沒有設(shè)置淘汰策略,這三個操作也都算關(guān)鍵路徑。因為如果Redis內(nèi)存超過了maxmemory,再寫入數(shù)據(jù)時,Redis返回的結(jié)果是OOM error,這種情況下,客戶端需要感知有錯誤發(fā)生才行。

注意:客戶端經(jīng)常會阻塞等待發(fā)送的命令返回結(jié)果,在上一個命令還沒有返回結(jié)果前,客戶端會一直等待,直到返回結(jié)果后,才會發(fā)送下一個命令。此時,即使我們不關(guān)心返回結(jié)果,客戶端也要等到寫操作執(zhí)行完成才行。所以,在不關(guān)心寫操作返回結(jié)果的場景下,可以對 Redis 客戶端做異步改造。具體點說,就是使用異步線程發(fā)送這些不關(guān)心返回結(jié)果的命令,而不是在 Redis 客戶端中等待這些命令的結(jié)果。

2.《為什么CPU結(jié)構(gòu)也會影響Redis的性能?》
1.CPU多核架構(gòu)
L1包括一級指令緩存和一級數(shù)據(jù)緩存;

**物理核的私有緩存,**它其實是指緩存空間只能被當(dāng)前的這個物理核使用,其他的物理核無法對這個核的緩存空間進行數(shù)據(jù)存取。

一個CPU有多個物理核(運行核心),每個物理核有自己私有的的L1,12緩存 ,這些緩存一般只有幾kb,但是訪問效率確是 納秒級別,一般不超過 10納秒;

如果 L1、L2 緩存中沒有所需的數(shù)據(jù),應(yīng)用程序就需要訪問內(nèi)存來獲取數(shù)據(jù)。

而應(yīng)用程序的訪存延遲一般在 百納秒級別,是訪問 L1、L2 緩存的延遲的近 10 倍,不可避免地會對性能造成影響。

所以,不同的物理核還會共享一個共同的三級緩存(Level 3 cache,簡稱為 L3 cache)

為了平衡cpu和內(nèi)存之間的差異,引入了 L3緩存(也就是CPU告訴緩存區(qū)),三級緩存不但平衡cpu L1,L2緩存與內(nèi)內(nèi)存訪問速度的差異,而且提升了 訪問容量,三級緩存容量可達到 幾MB,甚至 幾十MB ;

而且,CPU內(nèi) 多個物理核 之間共享 L3三級緩存;

另外:現(xiàn)在主流的 CPU 處理器中, 每個物理核 內(nèi)部有兩個邏輯核(超級線程),他們共享 物理核私有的L1,L2緩存;

下面看下 主流CPU架構(gòu)圖:

2.CPU多核架構(gòu)對Redis 性能的影響
在一個 CPU 核上運行時,應(yīng)用程序需要記錄自身使用的軟硬件資源信息(例如棧指針、CPU 核的寄存器值等),我們把這些信息稱為運行時信息。

同時,應(yīng)用程序訪問最頻繁的指令和數(shù)據(jù)還會被緩存到 L1、L2 緩存上,以便提升執(zhí)行速度。

但是,在多核 CPU 的場景下,一旦應(yīng)用程序需要在一個新的 CPU 核上運行,那么,運行時信息就需要重新加載到新的 CPU 核上。而且,新的 CPU 核的 L1、L2 緩存也需要重新加載數(shù)據(jù)和指令,這會導(dǎo)致程序的運行時間增加。

當(dāng) context switch 發(fā)生后,Redis 主線程的運行時信息需要被重新加載到另一個 CPU 核上,而且,此時,另一個 CPU 核上的 L1、L2 緩存中,并沒有 Redis 實例之前運行時頻繁訪問的指令和數(shù)據(jù),所以,這些指令和數(shù)據(jù)都需要重新從 L3 緩存,甚至是內(nèi)存中加載。這個重新加載的過程是需要花費一定時間的。而且,Redis 實例需要等待這個重新加載的過程完成后,才能開始處理請求,所以,這也會導(dǎo)致一些請求的處理時間增加。

在 CPU 多核場景下,Redis 實例被頻繁調(diào)度到不同 CPU 核上運行的話,那么,對 Redis 實例的請求處理時間影響就更大了。每調(diào)度一次,一些請求就會受到運行時信息、指令和數(shù)據(jù)重新加載過程的影響,這就會導(dǎo)致某些請求的延遲明顯高于其他請求。

所以,我們要避免 Redis 總是在不同 CPU 核上來回調(diào)度執(zhí)行。于是,我們嘗試著**把 Redis 實例和 CPU 核綁定了,讓一個 Redis 實例固定運行在一個 CPU 核上。**我們可以使用 taskset 命令把一個程序綁定在一個核上運行。比如說,我們執(zhí)行下面的命令,就把 Redis 實例綁在了 0 號核上,其中,“-c”選項用于設(shè)置要綁定的核編號。

taskset -c 0 ./redis-server
1
3.多CPU架構(gòu):NUMA
在主流的服務(wù)器上,一個 CPU 處理器會有 10 到 20 多個物理核。同時,為了提升服務(wù)器的處理能力,服務(wù)器上通常還會有多個 CPU 處理器(也稱為多 CPU Socket),每個處理器有自己的物理核(包括 L1、L2 緩存),L3 緩存,以及連接的內(nèi)存,同時,不同處理器間通過總線連接。

**在多 CPU 架構(gòu)上,應(yīng)用程序可以在不同的處理器上運行。**在剛才的圖中,Redis 可以先在 Socket 1 上運行一段時間,然后再被調(diào)度到 Socket 2 上運行。

如果應(yīng)用程序先在一個 Socket 上運行,并且把數(shù)據(jù)保存到了內(nèi)存,然后被調(diào)度到另一個 Socket 上運行,此時,應(yīng)用程序再進行內(nèi)存訪問時,就需要訪問之前 Socket 上連接的內(nèi)存,這種訪問屬于遠端內(nèi)存訪問。和訪問 Socket 直接連接的內(nèi)存相比,遠端內(nèi)存訪問會增加應(yīng)用程序的延遲。

4.NUMA架構(gòu)對redis性能影響
在實際應(yīng)用 Redis 時,我經(jīng)常看到一種做法,為了提升 Redis 的網(wǎng)絡(luò)性能,把操作系統(tǒng)的網(wǎng)絡(luò)中斷處理程序和 CPU 核綁定。

這個做法可以避免網(wǎng)絡(luò)中斷處理程序在不同核上來回調(diào)度執(zhí)行,的確能有效提升 Redis 的網(wǎng)絡(luò)處理性能。

但是,網(wǎng)絡(luò)中斷程序是要和 Redis 實例進行網(wǎng)絡(luò)數(shù)據(jù)交互的,一旦把網(wǎng)絡(luò)中斷程序綁核后,我們就需要注意 Redis 實例是綁在哪個核上了,這會關(guān)系到 Redis 訪問網(wǎng)絡(luò)數(shù)據(jù)的效率高低。

:網(wǎng)絡(luò)中斷處理程序從網(wǎng)卡硬件中讀取數(shù)據(jù),并把數(shù)據(jù)寫入到操作系統(tǒng)內(nèi)核維護的一塊內(nèi)存緩沖區(qū)。內(nèi)核會通過 epoll 機制觸發(fā)事件,通知 Redis 實例,Redis 實例再把數(shù)據(jù)從內(nèi)核的內(nèi)存緩沖區(qū)拷貝到自己的內(nèi)存空間,如下圖所示:

**潛在的風(fēng)險:**如果網(wǎng)絡(luò)中斷處理程序和 Redis 實例各自所綁的 CPU 核不在同一個 CPU Socket 上,那么,Redis 實例讀取網(wǎng)絡(luò)數(shù)據(jù)時,就需要跨 CPU Socket 訪問內(nèi)存,這個過程會花費較多時間。

所以,為了避免 Redis 跨 CPU Socket 訪問網(wǎng)絡(luò)數(shù)據(jù),我們最好把網(wǎng)絡(luò)中斷程序和 Redis 實例綁在同一個 CPU Socket 上

并不是先把一個 CPU Socket 中的所有邏輯核編完,再對下一個 CPU Socket 中的邏輯核編碼,而是先給每個 CPU Socket 中每個物理核的第一個邏輯核依次編號,再給每個 CPU Socket 中的物理核的第二個邏輯核依次編號。

假設(shè)有 2 個 CPU Socket,每個 Socket 上有 6 個物理核,每個物理核又有 2 個邏輯核,總共 24 個邏輯核。我們可以執(zhí)行 *lscpu 命令,*查看到這些核的編號:

lscpu

Architecture: x86_64
...
NUMA node0 CPU(s): 0-5,12-17
NUMA node1 CPU(s): 6-11,18-23
...
1
2
3
4
5
6
7
可以看到,NUMA node0 的 CPU 核編號是 0 到 5、12 到 17。其中,0 到 5 是 node0 上的 6 個物理核中的第一個邏輯核的編號,12 到 17 是相應(yīng)物理核中的第二個邏輯核編號。NUMA node1 的 CPU 核編號規(guī)則和 node0 一樣。

5.綁核的好處和壞處,以及解決方案
1.好處和壞處
好處:

在 CPU 多核的場景下,用 taskset 命令把 Redis 實例和一個核綁定,可以減少 Redis 實例在不同核上被來回調(diào)度執(zhí)行的開銷,避免較高的尾延遲;

在多 CPU 的 NUMA 架構(gòu)下,如果你對網(wǎng)絡(luò)中斷程序做了綁核操作,建議你同時把 Redis 實例和網(wǎng)絡(luò)中斷程序綁在同一個 CPU Socket 的不同核上,這樣可以避免 Redis 跨 Socket 訪問內(nèi)存中的網(wǎng)絡(luò)數(shù)據(jù)的時間開銷。

壞處:

把 Redis 實例綁到一個 CPU 邏輯核上時,就會導(dǎo)致子進程、后臺線程和 Redis 主線程競爭 CPU 資源,一旦子進程或后臺線程占用 CPU 時,主線程就會被阻塞,導(dǎo)致 Redis 請求延遲增加。

2.解決方案
a.一個 Redis 實例對應(yīng)綁一個物理核

按照上面的邏輯核編號,0,12 應(yīng)該在同一個物理核內(nèi),我們可以把一個redis實例綁定一個物理核:

taskset ? -c 0,12 ./redis-server
1
把 Redis 實例和物理核綁定,可以讓主線程、子進程、后臺線程共享使用 2 個邏輯核,可以在一定程度上緩解 CPU 資源競爭。但是,因為只用了 2 個邏輯核,它們相互之間的 CPU 競爭仍然還會存在。如果你還想進一步減少 CPU 競爭,我再給你介紹一種方案。

b.修改redis源碼

通過編程實現(xiàn)綁核時,要用到操作系統(tǒng)提供的 1 個數(shù)據(jù)結(jié)構(gòu) cpu_set_t 和 3 個函數(shù) CPU_ZERO、CPU_SET 和 sched_setaffinity,我先來解釋下它們。

cpu_set_t 數(shù)據(jù)結(jié)構(gòu):是一個位圖,每一位用來表示服務(wù)器上的一個 CPU 邏輯核。
CPU_ZERO 函數(shù):以 cpu_set_t 結(jié)構(gòu)的位圖為輸入?yún)?shù),把位圖中所有的位設(shè)置為 0。
CPU_SET 函數(shù):以 CPU 邏輯核編號和 cpu_set_t 位圖為參數(shù),把位圖中和輸入的邏輯核編號對應(yīng)的位設(shè)置為 1。
sched_setaffinity 函數(shù):以進程 / 線程 ID 號和 cpu_set_t 為參數(shù),檢查 cpu_set_t 中哪一位為 1,就把輸入的 ID 號所代表的進程 / 線程綁在對應(yīng)的邏輯核上。
那么,怎么在編程時把這三個函數(shù)結(jié)合起來實現(xiàn)綁核呢?

很簡單,我們分四步走就行。

第一步:創(chuàng)建一個 cpu_set_t 結(jié)構(gòu)的位圖變量;

第二步:使用 CPU_ZERO 函數(shù),把 cpu_set_t 結(jié)構(gòu)的位圖所有的位都設(shè)置為 0;

第三步:根據(jù)要綁定的邏輯核編號,使用 CPU_SET 函數(shù),把 cpu_set_t 結(jié)構(gòu)的位圖相應(yīng)位設(shè)置為 1;

第四步:使用 sched_setaffinity 函數(shù),把程序綁定在 cpu_set_t 結(jié)構(gòu)位圖中為 1 的邏輯核上。

對于 Redis 來說,它是在 bio.c 文件中的 bioProcessBackgroundJobs 函數(shù)中創(chuàng)建了后臺線程。bioProcessBackgroundJobs 函數(shù)類似于剛剛的例子中的 worker 函數(shù),在這個函數(shù)中實現(xiàn)綁核四步操作,就可以把后臺線程綁到和主線程不同的核上了。和給線程綁核類似,當(dāng)我們使用 fork 創(chuàng)建子進程時,也可以把剛剛說的四步操作實現(xiàn)在 fork 后的子進程代碼中,示例代碼如下:

int main(){
? ?//用fork創(chuàng)建一個子進程
? ?pid_t p = fork();
? ?if(p < 0){
? ? ? printf(" fork error\n");
? ?}
? ?//子進程代碼部分
? ?else if(!p){
? ? ? cpu_set_t cpuset; ?//創(chuàng)建位圖變量
? ? ? CPU_ZERO(&cpu_set); //位圖變量所有位設(shè)置0
? ? ? CPU_SET(3, &cpuset); //把位圖的第3位設(shè)置為1
? ? ? sched_setaffinity(0, sizeof(cpuset), &cpuset); ?//把程序綁定在3號邏輯核
? ? ? //實際子進程工作
? ? ? exit(0);
? ?}
? ?...
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
對于 Redis 來說,生成 RDB 和 AOF 日志重寫的子進程分別是下面兩個文件的函數(shù)中實現(xiàn)的。

rdb.c 文件:rdbSaveBackground 函數(shù);
aof.c 文件:rewriteAppendOnlyFileBackground 函數(shù)。
這兩個函數(shù)中都調(diào)用了 fork 創(chuàng)建子進程,所以,我們可以在子進程代碼部分加上綁核的四步操作。

3.《響應(yīng)波動延時:如何應(yīng)對redis變慢?》
1.redis真的變慢了嗎?
redis是否變慢需要根據(jù) Redis 的響應(yīng)延遲 與 redis實例的 基線性能比較 來判斷;

大部分時候,Redis 延遲很低,但是在某些時刻,有些 Redis 實例會出現(xiàn)很高的響應(yīng)延遲,甚至能達到幾秒到十幾秒,不過持續(xù)時間不長,這也叫延遲“毛刺”。當(dāng)你發(fā)現(xiàn) Redis 命令的執(zhí)行時間突然就增長到了幾秒,基本就可以認定 Redis 變慢了。

1.怎么測試redis的基線性能呢?
所謂的基線性能呢,也就是一個系統(tǒng)在低壓力、無干擾下的基本性能,這個性能只由當(dāng)前的軟硬件配置決定。

從 2.8.7 版本開始,<!–redis-cli 命令提供了–intrinsic-latency 選項,–>**可以用來監(jiān)測和統(tǒng)計測試期間內(nèi)的最大延遲,這個延遲可以作為 Redis 的基線性能。**一般情況下,運行 120 秒就足夠監(jiān)測到最大延遲了,所以,我們可以把參數(shù)設(shè)置為 120。

./redis-cli --intrinsic-latency 120
Max latency so far: 17 microseconds.
Max latency so far: 44 microseconds.
Max latency so far: 94 microseconds.
Max latency so far: 110 microseconds.
Max latency so far: 119 microseconds.

36481658 total runs (avg latency: 3.2893 microseconds / 3289.32 nanoseconds per run).
Worst run took 36x longer than the average latency.
1
2
3
4
5
6
7
8
9
可以看出當(dāng)前redis實例的最大延時是119 毫秒。

2. redis網(wǎng)絡(luò)延時 測試
如果你想了解網(wǎng)絡(luò)對 Redis 性能的影響,一個簡單的方法是用 iPerf 這樣的工具,測量從 Redis 客戶端到服務(wù)器端的網(wǎng)絡(luò)延遲。如果這個延遲有幾十毫秒甚至是幾百毫秒,就說明,Redis 運行的網(wǎng)絡(luò)環(huán)境中很可能有大流量的其他應(yīng)用程序在運行,導(dǎo)致網(wǎng)絡(luò)擁塞了。這個時候,你就需要協(xié)調(diào)網(wǎng)絡(luò)運維,調(diào)整網(wǎng)絡(luò)的流量分配了。

2.如何應(yīng)對redis變慢?
redis變慢排查我們可以從三個方面入手:

redis 自身特性
redis 文件系統(tǒng)
操作系統(tǒng)


1.redis 自身特性導(dǎo)致 變慢
1.慢查詢
Value 類型為 String 時,GET/SET 操作主要就是操作 Redis 的哈希表索引。這個操作復(fù)雜度基本是固定的,即 O(1)。但是,當(dāng) Value 類型為 Set 時,SORT、SUNION/SMEMBERS 操作復(fù)雜度分別為 O(N+M*log(M)) 和 O(N)。其中,N 為 Set 中的元素個數(shù),M 為 SORT 操作返回的元素個數(shù)。這個復(fù)雜度就增加了很多。

可以通過 Redis 日志,或者是 latency monitor 工具,查詢變慢的請求;

解決慢查詢:

用其他高效命令代替。比如說,如果你需要返回一個 SET 中的所有成員時,不要使用 SMEMBERS 命令,而是要使用 SSCAN 多次迭代返回,避免一次返回大量數(shù)據(jù),造成線程阻塞。
當(dāng)你需要執(zhí)行排序、交集、并集操作時,可以在客戶端完成,而不要用 SORT、SUNION、SINTER 這些命令,以免拖慢 Redis 實例。
KEYS 命令需要遍歷存儲的鍵值對,所以操作延時高,KEYS 命令一般不被建議用于生產(chǎn)環(huán)境中
2. 大量key 同時過期
過期 key 的自動刪除機制,默認情況下,Redis 每 100 毫秒會刪除一些過期 key:

采樣 ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 個數(shù)的 key,并將其中過期的 key 全部刪除;
如果超過 25% 的 key 過期了,則重復(fù)刪除的過程,直到過期 key 的比例降至 25% 以下。
ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 是 Redis 的一個參數(shù),默認是 20;

刪除操作是阻塞的(Redis 4.0 后可以用異步線程機制來減少阻塞影響),頻繁使用帶有相同時間參數(shù)的 EXPIREAT 命令設(shè)置過期 key,這就會導(dǎo)致,在同一秒內(nèi)有大量的 key 同時過期。那么就會導(dǎo)致一直執(zhí)行 第二步,阻塞redis

盡量設(shè)置不同的過期時間,可以在設(shè)置時添加一個隨機數(shù)。

2.redis文件系統(tǒng)
Redis 會持久化保存數(shù)據(jù)到磁盤,這個過程要依賴文件系統(tǒng)來完成,所以,文件系統(tǒng)將數(shù)據(jù)寫回磁盤的機制,會直接影響到 Redis 持久化的效率。而且,在持久化的過程中,Redis 也還在接收其他請求,持久化的效率高低又會影響到 Redis 處理請求的性能。

1.AOF日志模式
AOF 日志提供了三種日志寫回策略:no、everysec、always。這三種寫回策略依賴文件系統(tǒng)的兩個系統(tǒng)調(diào)用完成,也就是 write 和 fsync。

write 只要把日志記錄寫到內(nèi)核緩沖區(qū),就可以返回了,并不需要等待日志實際寫回到磁盤;

而 fsync 需要把日志記錄寫回到磁盤后才能返回,時間較長。

當(dāng)寫回策略配置為 everysec 時,Redis 會使用后臺的子線程異步完成 fsync 的操作。

而對于 always 策略來說,Redis 需要確保每個操作記錄日志都寫回磁盤,如果用后臺子線程異步完成,主線程就無法及時地知道每個操作是否已經(jīng)完成了,這就不符合 always 策略的要求了。所以,always 策略并不使用后臺子線程來執(zhí)行。

2.AOF重寫壓力過大導(dǎo)致fsync 阻塞
AOF重寫由子進程完成, 會有大量的IO操作;而fsync 雖然 是由后臺子線程完成寫入磁盤操作,但是,主線程在進行 寫操作時會監(jiān)視 fsync的執(zhí)行情況,如果子線程還未完成寫盤操作,主進程就會阻塞,不會返回給客戶端結(jié)果;

正是由于 主線程監(jiān)視 上一次fsync操作執(zhí)行情況,在寫磁盤壓力大時,可能導(dǎo)致 主線程阻塞;

例子:當(dāng)主線程使用后臺子線程執(zhí)行了一次 fsync,需要再次把新接收的操作記錄寫回磁盤時,如果主線程發(fā)現(xiàn)上一次的 fsync 還沒有執(zhí)行完,那么它就會阻塞。所以,如果后臺子線程執(zhí)行的 fsync 頻繁阻塞的話(比如 AOF 重寫占用了大量的磁盤 IO 帶寬),主線程也會阻塞,導(dǎo)致 Redis 性能變慢。

由于 fsync 后臺子線程和 AOF 重寫子進程的存在,主 IO 線程一般不會被阻塞。但是,如果在重寫日志時,AOF 重寫子進程的寫入量比較大,fsync 線程也會被阻塞,進而阻塞主線程,導(dǎo)致延遲增加。

如果業(yè)務(wù)應(yīng)用對延遲非常敏感,但同時允許一定量的數(shù)據(jù)丟失,那么,可以把配置項 no-appendfsync-on-rewrite 設(shè)置為 yes,如下所示:

no-appendfsync-on-rewrite yes
1
no-appendfsync-on-rewrite 表示 AOF重寫時選擇不 進行 fsync刷盤操作,yes表示可以不執(zhí)行fsync,no表示執(zhí)行fsync

針對延遲非常敏感,但同時允許一定量的數(shù)據(jù)丟失的應(yīng)用我們可以 設(shè)置no-appendfsync-on-rewrite yes

另外,我們可以采用高速的固態(tài)硬盤作為 AOF 日志的寫入設(shè)備。

3.操作系統(tǒng):swap和內(nèi)存大頁機制THP
1.Swap
內(nèi)存 swap 是操作系統(tǒng)里將內(nèi)存數(shù)據(jù)在內(nèi)存和磁盤間來回換入和換出的機制,涉及到磁盤的讀寫,所以,一旦觸發(fā) swap,無論是被換入數(shù)據(jù)的進程,還是被換出數(shù)據(jù)的進程,其性能都會受到慢速磁盤讀寫的影響。

一旦 swap 被觸發(fā)了,Redis 的請求操作需要等到磁盤數(shù)據(jù)讀寫完成才行,swap 觸發(fā)后影響的是 Redis 主 IO 線程,這會極大地增加 Redis 的響應(yīng)時間。

Redis 實例自身使用了大量的內(nèi)存,導(dǎo)致物理機器的可用內(nèi)存不足;
和 Redis 實例在同一臺機器上運行的其他進程,在進行大量的文件讀寫操作。文件讀寫本身會占用系統(tǒng)內(nèi)存,這會導(dǎo)致分配給 Redis 實例的內(nèi)存量變少,進而觸發(fā) Redis 發(fā)生 swap。
解決思路:

切片集群
加大內(nèi)存
1.首先查看redis進程號,這里是5332

$ redis-cli info | grep process_id
process_id: 5332
1
2
2.Redis 所在機器的 /proc 目錄下的該進程目錄中:

Redis 所在機器的 /proc 目錄下的該進程目錄中:
1
3.查看該 Redis 進程的使用情況,這里截取部分結(jié)果

$cat smaps | egrep '^(Swap|Size)'
Size: 584 kB
Swap: 0 kB
Size: 4 kB
Swap: 4 kB
Size: 4 kB
Swap: 0 kB
Size: 462044 kB
Swap: 462008 kB
Size: 21392 kB
Swap: 0 kB
1
2
3
4
5
6
7
8
9
10
11
Size 代表當(dāng)前redis所占內(nèi)存,Swap表示這塊 Size 大小的內(nèi)存區(qū)域有多少已經(jīng)被換出到磁盤上了。如果這兩個值相等,就表示這塊內(nèi)存區(qū)域已經(jīng)完全被換出到磁盤了。

2. 內(nèi)存大頁THP
該機制支持 2MB 大小的內(nèi)存頁分配,而常規(guī)的內(nèi)存頁分配是按 4KB 的粒度來執(zhí)行的。

Redis 為了提供數(shù)據(jù)可靠性保證,需要將數(shù)據(jù)做持久化保存。這個寫入過程由額外的線程執(zhí)行,所以,此時,Redis 主線程仍然可以接收客戶端寫請求。客戶端的寫請求可能會修改正在進行持久化的數(shù)據(jù)。在這一過程中,Redis 就會采用寫時復(fù)制機制,也就是說,一旦有數(shù)據(jù)要被修改,Redis 并不會直接修改內(nèi)存中的數(shù)據(jù),而是將這些數(shù)據(jù)拷貝一份,然后再進行修改。

如果采用了內(nèi)存大頁,那么,即使客戶端請求只修改 100B 的數(shù)據(jù),Redis 也需要拷貝 2MB 的大頁。相反,如果是常規(guī)內(nèi)存頁機制,只用拷貝 4KB。兩者相比,你可以看到,當(dāng)客戶端請求修改或新寫入數(shù)據(jù)較多時,內(nèi)存大頁機制將導(dǎo)致大量的拷貝,這就會影響 Redis 正常的訪存操作,最終導(dǎo)致性能變慢。

查看內(nèi)存大頁:

cat /sys/kernel/mm/transparent_hugepage/enabled
1
always代表使用了THP,never代表未使用

禁止使用THP:

echo never /sys/kernel/mm/transparent_hugepage/enabled
1
4.總結(jié)
梳理了一個包含 9 個檢查點的 Checklist,希望你在遇到 Redis 性能變慢時,按照這些步驟逐一檢查,高效地解決問題:

獲取 Redis 實例在當(dāng)前環(huán)境下的基線性能。
是否用了慢查詢命令?如果是的話,就使用其他命令替代慢查詢命令,或者把聚合計算命令放在客戶端做。
是否對過期 key 設(shè)置了相同的過期時間?對于批量刪除的 key,可以在每個 key 的過期時間上加一個隨機數(shù),避免同時刪除。
是否存在 bigkey? 對于 bigkey 的刪除操作,如果你的 Redis 是 4.0 及以上的版本,可以直接利用異步線程機制減少主線程阻塞;如果是 Redis 4.0 以前的版本,可以使用 SCAN 命令迭代刪除;對于 bigkey 的集合查詢和聚合操作,可以使用 SCAN 命令在客戶端完成。
Redis AOF 配置級別是什么?業(yè)務(wù)層面是否的確需要這一可靠性級別?如果我們需要高性能,同時也允許數(shù)據(jù)丟失,可以將配置項 no-appendfsync-on-rewrite 設(shè)置為 yes,避免 AOF 重寫和 fsync 競爭磁盤 IO 資源,導(dǎo)致 Redis 延遲增加。當(dāng)然, 如果既需要高性能又需要高可靠性,最好使用高速固態(tài)盤作為 AOF 日志的寫入盤。
Redis 實例的內(nèi)存使用是否過大?發(fā)生 swap 了嗎?如果是的話,就增加機器內(nèi)存,或者是使用 Redis 集群,分?jǐn)倖螜C Redis 的鍵值對數(shù)量和內(nèi)存壓力。同時,要避免出現(xiàn) Redis 和其他內(nèi)存需求大的應(yīng)用共享機器的情況。
在 Redis 實例的運行環(huán)境中,是否啟用了透明大頁機制?如果是的話,直接關(guān)閉內(nèi)存大頁機制就行了。
是否運行了 Redis 主從集群?如果是的話,把主庫實例的數(shù)據(jù)量大小控制在 2~4GB,以免主從復(fù)制時,從庫因加載大的 RDB 文件而阻塞。
是否使用了多核 CPU 或 NUMA 架構(gòu)的機器運行 Redis 實例?使用多核 CPU 時,可以給 Redis 實例綁定物理核;使用 NUMA 架構(gòu)時,注意把 Redis 實例和網(wǎng)絡(luò)中斷處理程序運行在同一個 CPU Socket 上。
4.redis 中 的內(nèi)存碎片
1. 內(nèi)存碎片帶來的影響?
question 1: 為什么redis已經(jīng)刪除了數(shù)據(jù),使用top命令還會顯示redis 內(nèi)存占用較大呢?

那是因為redis雖然刪除了這些數(shù)據(jù),回收了內(nèi)存空間,但是 redis內(nèi)存分配器不會立刻把 內(nèi)存空間 返還給操作系統(tǒng);

所以,出現(xiàn)redis已經(jīng)刪除了數(shù)據(jù),但是 任務(wù)管理器還會顯示redis占用大內(nèi)存的情況;

question 2: redis 由內(nèi)存分配器回收,分配內(nèi)存,如果沒有內(nèi)存自動整理功能(整理內(nèi)存碎片),會有什么風(fēng)險?

即使有大量的內(nèi)存 ,但是空間碎片較多,內(nèi)存利用率低, 當(dāng)寫 bigkey 要求分配大量且連續(xù)的內(nèi)存空間時,沒有較大的連續(xù)內(nèi)存空間導(dǎo)致無法處理這個操作;

雖然有空閑空間,Redis 卻無法用來保存數(shù)據(jù),不僅會減少 Redis 能夠?qū)嶋H保存的數(shù)據(jù)量,還會降低 Redis 運行機器的成本回報率。

2.內(nèi)存碎片如何形成的?
主要有兩種方式:

內(nèi)因:操作系統(tǒng)的內(nèi)存分配機制
外因:Redis 的負載特征(鍵值大小不一致, 鍵值對修改,刪除等)
1. 內(nèi)因:內(nèi)存分配器的分配策略
Redis 可以使用 libc、jemalloc、tcmalloc 多種內(nèi)存分配器來分配內(nèi)存,默認使用 jemalloc。

jemalloc 的分配策略之一,是按照一系列固定的大小劃分內(nèi)存空間。例如 8 字節(jié)、16 字節(jié)、32 字節(jié)、48 字節(jié),…, 2KB、4KB、8KB 等。當(dāng)程序申請的內(nèi)存最接近某個固定值時,jemalloc 會給它分配相應(yīng)大小的空間。

這樣的分配方式本身是為了減少分配次數(shù)。例如,Redis 申請一個 20 字節(jié)的空間保存數(shù)據(jù),jemalloc 就會分配 32 字節(jié),此時,如果應(yīng)用還要寫入 10 字節(jié)的數(shù)據(jù),Redis 就不用再向操作系統(tǒng)申請空間了,因為剛才分配的 32 字節(jié)已經(jīng)夠用了,這就避免了一次分配操作。

2.外因:鍵值對大小不一樣和刪改操作
不同大小的鍵值對,Redis 申請內(nèi)存空間分配時,本身就會有大小不一的空間需求。
鍵值對修改刪除帶來的內(nèi)存空間變化,刪除和修改都會帶來空間碎片;
3.redis內(nèi)存碎片處理
1.判斷是否有內(nèi)存碎片
INFO memory
# Memory
used_memory:1073741736
used_memory_human:1024.00M
used_memory_rss:1997159792
used_memory_rss_human:1.86G

mem_fragmentation_ratio:1.86
1
2
3
4
5
6
7
8
mem_fragmentation_ratio: 表示Redis 當(dāng)前的內(nèi)存碎片率。它就是上面的命令中的兩個指標(biāo) used_memory_rss 和 used_memory 相除的結(jié)果。

used_memory_rss:操作系統(tǒng)實際分配給 Redis 的物理內(nèi)存空間,里面就包含了碎片

used_memory :redis 申請的內(nèi)存空間

問題:那么,該如何設(shè)置這個mem_fragmentation_ratio的值呢?這里有一些經(jīng)驗設(shè)置閾值:

1 <= mem_fragmentation_ratio <= 1.5:這種情況是合理的。
mem_fragmentation_ratio > 1.5 :這表明內(nèi)存碎片率已經(jīng)超過了 50%。一般情況下,這個時候,我們就需要采取一些措施來降低內(nèi)存碎片率了。
2.內(nèi)存碎片的清理
a.內(nèi)存清理
從 4.0-RC3 版本以后,Redis 自身提供了一種內(nèi)存碎片自動清理的方法,我們先來看這個方法的基本機制。

內(nèi)存碎片清理,簡單來說,就是**“搬家讓位,合并空間”**。

碎片清理是有代價的:

操作系統(tǒng)需要把多份數(shù)據(jù)拷貝到新位置,把原有空間釋放出來,這會帶來時間開銷。

因為 Redis 是單線程,在數(shù)據(jù)拷貝時,Redis 只能等著,這就導(dǎo)致 Redis 無法及時處理請求,性能就會降低。

而且,有的時候,數(shù)據(jù)拷貝還需要注意順序,就像剛剛說的清理內(nèi)存碎片的例子,操作系統(tǒng)需要先拷貝 D,并釋放 D 的空間后,才能拷貝 B。這種對順序性的要求,會進一步增加 Redis 的等待時間,導(dǎo)致性能降低。

b.如何 降低內(nèi)存清理時對redis性能的影響?
啟動內(nèi)存碎片自動清理:

config set activedefrag yes
1
主要從兩個方面三個參數(shù)控制內(nèi)存清理:

滿足兩個條件自動進行內(nèi)存清理:
active-defrag-ignore-bytes 100mb:內(nèi)存碎片字節(jié)數(shù)到達100MB
active-defrag-threshold-lower 10:表示內(nèi)存碎片空間占操作系統(tǒng)分配給 Redis 的總空間比例達到 10% 時,開始清理。
注意:清理過程中,不滿足以上條件時立刻停止自動清理,滿足條件后會繼續(xù)自動清理
控制內(nèi)存碎片CPU執(zhí)行時間:
active-defrag-cycle-min 25: 表示自動清理過程所用 CPU 時間的比例不低于 25%,保證清理能正常開展;
active-defrag-cycle-max 75:表示自動清理過程所用 CPU 時間的比例不高于 75%,一旦超過,就停止清理,從而避免在清理時,大量的內(nèi)存拷貝阻塞 Redis,導(dǎo)致響應(yīng)延遲升高。
5.《redis 緩沖區(qū)》
1. 什么是緩沖區(qū)?
1.緩沖區(qū)解決什么問題?

redis緩沖區(qū)解決客戶端請求堆積或服務(wù)器處理數(shù)據(jù)速度過慢帶來的數(shù)據(jù)丟失以及性能問題。

2.緩沖區(qū)在redis 中有哪些應(yīng)用場景?

cliet-server服務(wù)器模式高并發(fā)下暫存客戶端發(fā)送的命令數(shù)據(jù),或者是服務(wù)器端返回給客戶端的數(shù)據(jù)結(jié)果
主從節(jié)點間進行數(shù)據(jù)同步時,用來暫存主節(jié)點接收的寫命令和數(shù)據(jù)。
注意:redis之所以適合做緩存是因為它有高性能的內(nèi)存結(jié)構(gòu) ,以及完善的淘汰機制;

2.客戶端與服務(wù)器之間的緩沖區(qū)


cliet-server模式之間的緩沖區(qū),分為輸入緩沖區(qū)的輸出緩沖區(qū),服務(wù)器端給每個連接的客戶端都設(shè)置了一個輸入緩沖區(qū)和輸出緩沖區(qū)

client把請求命令和數(shù)據(jù) 放入 輸入緩沖區(qū),server 逐步讀取命令把執(zhí)行結(jié)果發(fā)送到輸出緩沖區(qū),client去輸出緩沖區(qū)拿響應(yīng)結(jié)果。

3.如何處理輸入緩沖區(qū)溢出問題
1.查看輸入緩沖區(qū)使用情況
CLIENT LIST
id=5 addr=127.0.0.1:50487 fd=9 name= age=4 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=26 qbuf-free=32742 obl=0 oll=0 omem=0 events=r cmd=client
1
2
client list 命令查看所有與server 相連的客戶端輸入緩沖區(qū)的信息

主要看兩類信息:

client 的信息,ip 地址,端口號

輸入緩沖區(qū)相關(guān)信息:

? cmd: 客戶端最新執(zhí)行的命令(當(dāng)前為client)

? qbuf: 當(dāng)前客戶端已使用 緩沖區(qū)大小

? qbuf-free: 剩余 緩沖區(qū)大小

2.什么情況下出現(xiàn)輸入緩沖區(qū)溢出問題?以及解決方案
有批量bigkey請求
server性能低, 頻繁阻塞或阻塞時間教久
怎么解決呢?

由于輸入緩沖區(qū) 并不能設(shè)置緩沖區(qū)的大小,默認最多1G,所有只能避免bigkey ,避免server性能低

注意:當(dāng)多個客戶端連接占用的內(nèi)存總量,超過了 Redis 的 maxmemory 配置項時(例如 4GB),就會觸發(fā) Redis 進行數(shù)據(jù)淘汰。

4.如何處理輸出緩存沖溢出問題?
1.什么情況下出現(xiàn)輸出緩沖區(qū)溢出問題?
輸出bigkey結(jié)果
執(zhí)行MONITOR
輸出緩沖區(qū)設(shè)置過小
2.怎么設(shè)置輸出緩沖區(qū)的大小?
client-output-buffer-limit 配置項,來設(shè)置緩沖區(qū)的大小

例子:client-output-buffer-limit normal 0 0 0

四個參數(shù)代表什么?

one:類型,normal代表普通客戶端

two: 緩沖區(qū)最大限制

three : 持續(xù)輸出最大的數(shù)據(jù)量

four:持續(xù)輸出最大時間

3.不同的客戶端不同分配模式
普通客戶端

?client-output-buffer-limit normal 0 0 0
1
普通客戶端來說,它每發(fā)送完一個請求,會等到請求結(jié)果返回后,再發(fā)送下一個請求,這種發(fā)送方式稱為阻塞式發(fā)送。在這種情況下,如果不是讀取體量特別大的 bigkey,服務(wù)器端的輸出緩沖區(qū)一般不會被阻塞的。

所以,我們通常把普通客戶端的緩沖區(qū)大小限制,以及持續(xù)寫入量限制、持續(xù)寫入時間限制都設(shè)置為 0,也就是不做限制。

訂閱客戶端

一旦訂閱的 Redis 頻道有消息了,服務(wù)器端都會通過輸出緩沖區(qū)把消息發(fā)給客戶端。所以,訂閱客戶端和服務(wù)器間的消息發(fā)送方式,不屬于阻塞式發(fā)送。

因此,我們會給訂閱客戶端設(shè)置緩沖區(qū)大小限制、緩沖區(qū)持續(xù)寫入量限制,以及持續(xù)寫入時間限制,可以在 Redis 配置文件中這樣設(shè)置:

client-output-buffer-limit pubsub 8mb 2mb 60
1
5.主從集群中的緩沖區(qū)
1.復(fù)制緩沖區(qū)(replication_buffer)
replication_buffer的大小不算入 maxmemory

在全量復(fù)制過程中,主節(jié)點在向從節(jié)點傳輸 RDB 文件的同時,會繼續(xù)接收客戶端發(fā)送的寫命令請求。這些寫命令就會先保存在復(fù)制緩沖區(qū)中,主節(jié)點上會為每個從節(jié)點都維護一個復(fù)制緩沖區(qū),來保證主從節(jié)點間的數(shù)據(jù)同步。

按通常的使用經(jīng)驗,我們會**把主節(jié)點的數(shù)據(jù)量控制在 2~4GB,**這樣可以讓全量同步執(zhí)行得更快些,避免復(fù)制緩沖區(qū)累積過多命令。

config set client-output-buffer-limit slave 512mb 128mb 60
1
2.復(fù)制積壓緩沖區(qū)(repl_backlog_buffer)
repl_backlog_buffer算入maxmemeory

增量復(fù)制時使用的緩沖區(qū),這個緩沖區(qū)稱為復(fù)制積壓緩沖區(qū),為了應(yīng)對復(fù)制積壓緩沖區(qū)的溢出問題,我們可以調(diào)整復(fù)制積壓緩沖區(qū)的大小,也就是設(shè)置 repl_backlog_size 這個參數(shù)的值.

6. 總結(jié)
針對命令數(shù)據(jù)發(fā)送過快過大的問題,對于普通客戶端來說可以避免 bigkey,而對于復(fù)制緩沖區(qū)來說,就是避免過大的 RDB 文件。
針對命令數(shù)據(jù)處理較慢的問題,解決方案就是減少 Redis 主線程上的阻塞操作,例如使用異步的刪除操作。
針對緩沖區(qū)空間過小的問題,解決方案就是使用 client-output-buffer-limit 配置項設(shè)置合理的輸出緩沖區(qū)、復(fù)制緩沖區(qū)和復(fù)制積壓緩沖區(qū)大小。當(dāng)然,我們不要忘了,輸入緩沖區(qū)的大小默認是固定的,我們無法通過配置來修改它,除非直接去修改 Redis 源碼。
?

總結(jié)

以上是生活随笔為你收集整理的redis核心技术与实战(三) 性能篇的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。