自我系統(tǒng)學(xué)習(xí)Redis小記-01

00 | 開篇詞 | 這樣學(xué)Redis,才能技高一籌

1、思考

為了保證數(shù)據(jù)的可靠性鸽凶,Redis 需要在磁盤上讀寫 AOF 和 RDB篮赢,但在高并發(fā)場(chǎng)景里齿椅,這就會(huì)直接帶來(lái)兩個(gè)新問題:一個(gè)是寫 AOF 和RDB 會(huì)造成 Redis 性能抖動(dòng),另一個(gè)是 Redis 集群數(shù)據(jù)同步和實(shí)例恢復(fù)時(shí)启泣,讀 RDB 比較慢涣脚,限制了同步和恢復(fù)速度。

其實(shí)寥茫,一個(gè)可行的解決方案就是使用非易失內(nèi)存 NVM遣蚀,因?yàn)樗饶鼙WC高速的讀寫,又能快速持久化數(shù)據(jù)纱耻。

2芭梯、長(zhǎng)尾延遲

Redis 處理了 100 個(gè)請(qǐng)求,99 個(gè)請(qǐng)求的響應(yīng)時(shí)間都是 1s弄喘,而有一個(gè)請(qǐng)求的響應(yīng)時(shí)間是 100s玖喘。那么,如果看平均延遲蘑志,這 100 個(gè)請(qǐng)求的平均延遲是 1.99s累奈,但是對(duì)于這個(gè)響應(yīng)時(shí)間是 100s 的請(qǐng)求而言,它對(duì)應(yīng)的用戶體驗(yàn)將是非常糟糕的急但。這一個(gè)請(qǐng)求就是長(zhǎng)尾延遲澎媒。

3、redis知識(shí)圖譜:“兩大維度”就是指系統(tǒng)維度和應(yīng)用維度羊始,“三大主線”也就是指高性能旱幼、高可靠和高可擴(kuò)展(可以簡(jiǎn)稱為“三高”)。

4突委、三大主線

高性能主線柏卤,包括線程模型、數(shù)據(jù)結(jié)構(gòu)匀油、持久化缘缚、網(wǎng)絡(luò)框架;

高可靠主線敌蚜,包括主從復(fù)制桥滨、哨兵機(jī)制;

高可擴(kuò)展主線,包括數(shù)據(jù)分片齐媒、負(fù)載均衡蒲每。

5、Redis 的問題畫像圖

舉個(gè)例子喻括,如果你遇到了 Redis 的響應(yīng)變慢問題邀杏,對(duì)照著這張圖(“問題 --> 主線 --> 技術(shù)點(diǎn)”),你就可以發(fā)現(xiàn)唬血,這個(gè)問題和 Redis 的性能主線相關(guān)望蜡,而性能主線又和數(shù)據(jù)結(jié)構(gòu)、異步機(jī)制拷恨、RDB脖律、AOF 重寫相關(guān)。找到了影響的因素腕侄,解決起來(lái)也就很容易了小泉。

6、Redis在 CPU 使用兜挨、內(nèi)存組織膏孟、存儲(chǔ)持久化和網(wǎng)絡(luò)通信這四大方面的設(shè)計(jì)非常經(jīng)典

CPU 使用上的“坑”,例如數(shù)據(jù)結(jié)構(gòu)的復(fù)雜度拌汇、跨 CPU 核的訪問柒桑;

內(nèi)存使用上的“坑”,例如主從同步和 AOF 的內(nèi)存競(jìng)爭(zhēng)噪舀;

存儲(chǔ)持久化上的“坑”魁淳,例如在 SSD 上做快照的性能抖動(dòng);

網(wǎng)絡(luò)通信上的“坑”与倡,例如多實(shí)例時(shí)的異常網(wǎng)絡(luò)丟包界逛。




01 | 基本架構(gòu):一個(gè)鍵值數(shù)據(jù)庫(kù)包含什么?

1纺座、SimpleKV看似簡(jiǎn)單息拜,實(shí)際上卻是我們理解 Redis 經(jīng)常被用于緩存、秒殺净响、分布式鎖等場(chǎng)景的重要基礎(chǔ)少欺。

2、它支持的 value 類型馋贤,Redis 能夠在實(shí)際業(yè)務(wù)場(chǎng)景中得到廣泛的應(yīng)用赞别,就是得益于支持多樣化類型的 value

例如配乓,Memcached支持的 value 類型僅為 String 類型仿滔,而 Redis 支持的 value 類型包括了 String惠毁、哈希表、列表崎页、集合等鞠绰。

3、SimpleKV 需要支持的 3 種基本操作飒焦,即 PUT洞豁、GET 和 DELETE。

需要注意的是荒给,有些鍵值數(shù)據(jù)庫(kù)的新寫 / 更新操作叫 SET。新寫入和更新雖然是用一個(gè)操作接口刁卜,但在實(shí)際執(zhí)行時(shí)志电,會(huì)根據(jù) key 是否存在而執(zhí)行相應(yīng)的新寫或更新流程蛔趴。

PUT:新寫入或更新一個(gè) key-value 對(duì);

GET:根據(jù)一個(gè) key 讀取相應(yīng)的 value 值;

DELETE:根據(jù)一個(gè) key 刪除整個(gè) key-value 對(duì)。

SCAN :根據(jù)一段 key 的范圍返回相應(yīng)的 value值。

因此印叁,PUT/GET/DELETE/SCAN 是一個(gè)鍵值數(shù)據(jù)庫(kù)的基本操作集合。

另:需要判斷某個(gè)用戶是否存在。如果將該用戶的 ID 作為 key闲延,那么找颓,可以增加 EXISTS 操作接口,用于判斷某個(gè) key 是否存在。

4、考慮一個(gè)非常重要的設(shè)計(jì)問題:鍵值對(duì)保存在內(nèi)存還是外存?

1)棒拂、保存在內(nèi)存的好處是讀寫很快琐旁,畢竟內(nèi)存的訪問速度一般都在百 ns 級(jí)別敬特。但是,潛在的風(fēng)險(xiǎn)是一旦掉電,所有的數(shù)據(jù)都會(huì)丟失。

2)、保存在外存,雖然可以避免數(shù)據(jù)丟失夷野,但是受限于磁盤的慢速讀寫(通常在幾 ms 級(jí)別),鍵值數(shù)據(jù)庫(kù)的整體性能會(huì)被拉低荣倾。

因此扫责,如何進(jìn)行設(shè)計(jì)選擇,我們通常需要考慮鍵值數(shù)據(jù)庫(kù)的主要應(yīng)用場(chǎng)景逃呼。

Memcached 和 Redis 都是屬于內(nèi)存鍵值數(shù)據(jù)庫(kù)。

5者娱、大體來(lái)說(shuō)抡笼,一個(gè)鍵值數(shù)據(jù)庫(kù)包括了訪問框架、索引模塊黄鳍、操作模塊和存儲(chǔ)模塊四部分

6推姻、采用什么訪問模式?

一種是通過(guò)函數(shù)庫(kù)調(diào)用的方式供外部應(yīng)用使用框沟;另一種是通過(guò)網(wǎng)絡(luò)框架以 Socket 通信的形式對(duì)外提供鍵值對(duì)操作

7藏古、如何定位鍵值對(duì)的位置?

SimpleKV需要查找所要操作的鍵值對(duì)是否存在忍燥,這依賴于鍵值數(shù)據(jù)庫(kù)的索引模塊拧晕。索引的作用是讓鍵值數(shù)據(jù)庫(kù)根據(jù) key 找到相應(yīng) value 的存儲(chǔ)位置,進(jìn)而執(zhí)行操作梅垄。

注意:Memcached 和 Redis 采用哈希表作為 key-value 索引厂捞,而 RocksDB 則采用跳表作為內(nèi)存中 key-value 的索引

一般而言,內(nèi)存鍵值數(shù)據(jù)庫(kù)(例如 Redis)采用哈希表作為索引队丝,很大一部分原因在于靡馁,其鍵值數(shù)據(jù)基本都是保存在內(nèi)存中的,而內(nèi)存的高性能隨機(jī)訪問特性可以很好地與哈希表O(1) 的操作復(fù)雜度相匹配机久。

8臭墨、不同操作的具體邏輯是怎樣的?

對(duì)于 GET/SCAN 操作而言膘盖,此時(shí)根據(jù) value 的存儲(chǔ)位置返回 value 值即可胧弛;

對(duì)于 PUT 一個(gè)新的鍵值對(duì)數(shù)據(jù)而言尤误,SimpleKV 需要為該鍵值對(duì)分配內(nèi)存空間;

對(duì)于 DELETE 操作叶圃,SimpleKV 需要?jiǎng)h除鍵值對(duì)袄膏,并釋放相應(yīng)的內(nèi)存空間,這個(gè)過(guò)程由分配器完成掺冠。

9沉馆、如何實(shí)現(xiàn)重啟后快速提供服務(wù)?

SimpleKV 采用了常用的內(nèi)存分配器 glibc 的 malloc 和 free德崭,因此斥黑,SimpleKV 并不需要特別考慮內(nèi)存空間的管理問題。

10眉厨、小結(jié)

從 SimpleKV 演進(jìn)到 Redis锌奴,有以下幾個(gè)重要變化:

1)、Redis 主要通過(guò)網(wǎng)絡(luò)框架進(jìn)行訪問憾股,而不再是動(dòng)態(tài)庫(kù)了鹿蜀,這也使得 Redis 可以作為一個(gè)基礎(chǔ)性的網(wǎng)絡(luò)服務(wù)進(jìn)行訪問,擴(kuò)大了 Redis 的應(yīng)用范圍服球。

2)茴恰、Redis 數(shù)據(jù)模型中的 value 類型很豐富,因此也帶來(lái)了更多的操作接口斩熊,例如面向列表的 LPUSH/LPOP往枣,面向集合的 SADD/SREM 等。在下節(jié)課粉渠,我將和你聊聊這些 value模型背后的數(shù)據(jù)結(jié)構(gòu)和操作效率分冈,以及它們對(duì) Redis 性能的影響。

3)霸株、Redis 的持久化模塊能支持兩種方式:日志(AOF)和快照(RDB)雕沉,這兩種持久化方式具有不同的優(yōu)劣勢(shì),影響到 Redis 的訪問性能和可靠性去件。

4)蘑秽、SimpleKV 是個(gè)簡(jiǎn)單的單機(jī)鍵值數(shù)據(jù)庫(kù),但是箫攀,Redis 支持高可靠集群和高可擴(kuò)展集群肠牲,因此,Redis 中包含了相應(yīng)的集群功能支撐模塊靴跛。


02 | 數(shù)據(jù)結(jié)構(gòu):快速的Redis有哪些慢操作缀雳?

1、它接收到一個(gè)鍵值對(duì)操作后梢睛,能以微秒級(jí)別的速度找到數(shù)據(jù)肥印,并快速完成操作识椰。

數(shù)據(jù)庫(kù)這么多,為啥 Redis 能有這么突出的表現(xiàn)呢深碱?

一方面腹鹉,這是因?yàn)樗莾?nèi)存數(shù)據(jù)庫(kù),所有操作都在內(nèi)存上完成敷硅,內(nèi)存的訪問速度本身就很快功咒。

另一方面,這要?dú)w功于它的數(shù)據(jù)結(jié)構(gòu)绞蹦。這是因?yàn)榱Ψ埽I值對(duì)是按一定的數(shù)據(jù)結(jié)構(gòu)來(lái)組織的,操作鍵值對(duì)最終就是對(duì)數(shù)據(jù)結(jié)構(gòu)進(jìn)行增刪改查操作幽七,所以高效的數(shù)據(jù)結(jié)構(gòu)是 Redis 快速處理數(shù)據(jù)的基礎(chǔ)景殷。

2、數(shù)據(jù)結(jié)構(gòu)的底層實(shí)現(xiàn)

底層數(shù)據(jù)結(jié)構(gòu)一共有 6 種澡屡,分別是簡(jiǎn)單動(dòng)態(tài)字符串猿挚、雙向鏈表、壓縮列表驶鹉、哈希表绩蜻、跳表、整數(shù)數(shù)組梁厉。


String 類型的底層實(shí)現(xiàn)只有一種數(shù)據(jù)結(jié)構(gòu),也就是簡(jiǎn)單動(dòng)態(tài)字符串踏兜。而 List词顾、Hash、Set 和 Sorted Set 這四種數(shù)據(jù)類型碱妆,都有兩種底層實(shí)現(xiàn)結(jié)構(gòu)肉盹。通常情況下,我們會(huì)把這四種類型稱為集合類型疹尾,它們的特點(diǎn)是一個(gè)鍵對(duì)應(yīng)了一個(gè)集合的數(shù)據(jù)上忍。

3、鍵和值用什么結(jié)構(gòu)組織纳本?

Redis 使用了一個(gè)哈希表O(1)來(lái)保存所有鍵值對(duì)窍蓝。

哈希桶中的元素保存的并不是值本身,而是指向具體值的指針繁成。

也就是說(shuō)吓笙,不管值是 String,還是集合類型巾腕,哈希桶中的元素都是指向它們的指針面睛。

哈希桶中的 entry 元素中保存了*key和*value指針絮蒿,分別指向了實(shí)際的鍵和值,這樣一來(lái)叁鉴,即使值是一個(gè)集合土涝,也可以通過(guò)*value指針被查找到。

全局哈希表

這個(gè)哈希表保存了所有的鍵值對(duì)幌墓,所以但壮,我也把它稱為全局哈希表

好處是:用O(1) 的時(shí)間復(fù)雜度來(lái)快速查找到鍵值對(duì)

突然變慢:Redis中存在大量數(shù)據(jù)后克锣,會(huì)突然變慢茵肃,潛在問題就是哈希表的沖突問題和 rehash 可能帶來(lái)的操作阻塞

4袭祟、為什么哈希表操作變慢了验残?

1)、解決hash沖突:鏈?zhǔn)焦#?b>同一個(gè)哈希桶中的多個(gè)元素用一個(gè)鏈表來(lái)保存巾乳,它們之間依次用指針連接您没。

2)、所以胆绊,Redis 會(huì)對(duì)哈希表做 rehash 操作氨鹏。rehash 也就是增加現(xiàn)有的哈希桶數(shù)量,讓逐漸

增多的 entry 元素能在更多的桶之間分散保存压状,減少單個(gè)桶中的元素?cái)?shù)量仆抵,從而減少單個(gè)

桶中的沖突。那具體怎么做呢种冬?

3)镣丑、其實(shí),為了使 rehash 操作更高效娱两,Redis 默認(rèn)使用了兩個(gè)全局哈希表:哈希表 1 和哈希

表 2莺匠。一開始,當(dāng)你剛插入數(shù)據(jù)時(shí)十兢,默認(rèn)使用哈希表 1趣竣,此時(shí)的哈希表 2 并沒有被分配空

間。隨著數(shù)據(jù)逐步增多旱物,Redis 開始執(zhí)行 rehash遥缕,這個(gè)過(guò)程分為三步:

a. 給哈希表 2 分配更大的空間,例如是當(dāng)前哈希表 1 大小的兩倍宵呛;

b. 把哈希表 1 中的數(shù)據(jù)重新映射并拷貝到哈希表 2 中通砍;

c. 釋放哈希表 1 的空間。

4)、到此封孙,我們就可以從哈希表 1 切換到哈希表 2迹冤,用增大的哈希表 2 保存更多數(shù)據(jù),而原來(lái)的哈希表 1 留作下一次 rehash 擴(kuò)容備用虎忌。

但是第二次拷貝數(shù)據(jù)數(shù)據(jù)量大泡徙,如果一次性把哈希表 1 中的數(shù)據(jù)都遷移完,會(huì)造成 Redis 線程阻塞膜蠢,無(wú)法服務(wù)其他請(qǐng)求堪藐,此時(shí)Redis采用漸進(jìn)性rehash


漸進(jìn)式rehash

5、集合數(shù)據(jù)操作效率

首先挑围,與集合的底層數(shù)據(jù)結(jié)構(gòu)有關(guān)礁竞,其次,操作效率和這些操作本身的執(zhí)行特點(diǎn)有關(guān)杉辙,比如讀第一個(gè)比讀所有快

6模捂、有哪些底層數(shù)據(jù)結(jié)構(gòu)?

1)蜘矢、hash表上面已經(jīng)寫過(guò)了狂男,操作復(fù)雜度是O(1)

2)、整數(shù)數(shù)組雙向鏈表也很常見品腹,它們的操作特征都是順序讀寫岖食,也就是通過(guò)數(shù)組下標(biāo)或者鏈表的指針逐個(gè)元素訪問,操作復(fù)雜度基本是 O(N)舞吭,操作效率比較低

3)泡垃、壓縮列表

壓縮列表實(shí)際上類似于一個(gè)數(shù)組,數(shù)組中的每一個(gè)元素都對(duì)應(yīng)保存一個(gè)數(shù)據(jù)羡鸥。和數(shù)組不同的是蔑穴,壓縮列表在表頭有三個(gè)字段 zlbytes、zltail 和 zllen兄春,分別表示列表長(zhǎng)度澎剥、列表尾的偏移量和列表中的 entry 個(gè)數(shù)锡溯;壓縮列表在表尾還有一個(gè) zlend赶舆,表示列表結(jié)束

壓縮列表

在壓縮列表中祭饭,如果我們要查找定位第一個(gè)元素和最后一個(gè)元素芜茵,可以通過(guò)表頭三個(gè)字段的長(zhǎng)度直接定位,復(fù)雜度是 O(1)倡蝙。而查找其他元素時(shí)九串,就沒有這么高效了,只能逐個(gè)查找,此時(shí)的復(fù)雜度就是 O(N) 了猪钮。

4)品山、跳表??O(logN)

有序鏈表只能逐一查找元素,導(dǎo)致操作起來(lái)非常緩慢烤低,于是就出現(xiàn)了跳表肘交。具體來(lái)說(shuō),跳表在鏈表的基礎(chǔ)上扑馁,增加了多級(jí)索引涯呻,通過(guò)索引位置的幾個(gè)跳轉(zhuǎn),實(shí)現(xiàn)數(shù)據(jù)的快速定位

跳表快速查找過(guò)程

7腻要、各個(gè)數(shù)據(jù)結(jié)構(gòu)的操作時(shí)間復(fù)雜度

8复罐、不同操作的復(fù)雜度

集合類型的操作類型很多,有讀寫單個(gè)集合元素的雄家,例如 HGET效诅、HSET,也有操作多個(gè)元素的咳短,例如 SADD填帽,還有對(duì)整個(gè)集合進(jìn)行遍歷操作的,例如 SMEMBERS咙好。這么多操作篡腌,它們的復(fù)雜度也各不相同。而復(fù)雜度的高低又是我們選擇集合類型的重要依據(jù)勾效。下面四句口訣:

單元素操作是基礎(chǔ)嘹悼;

范圍操作非常耗時(shí);

統(tǒng)計(jì)操作通常高效层宫;

例外情況只有幾個(gè)杨伙。

1)、單元素操作萌腿,是指每一種集合類型對(duì)單個(gè)數(shù)據(jù)實(shí)現(xiàn)的增刪改查操作限匣。

2)、范圍操作毁菱,是指集合類型中的遍歷操作米死,可以返回集合中的所有數(shù)據(jù),這類操作的復(fù)雜度一般是 O(N)贮庞,比較耗時(shí)峦筒,我們應(yīng)該盡量避免。

3)窗慎、統(tǒng)計(jì)操作物喷,是指集合類型對(duì)集合中所有元素個(gè)數(shù)的記錄卤材,操作復(fù)雜度只有 O(1),這是因?yàn)楫?dāng)集合類型采用壓縮列表峦失、雙向鏈表扇丛、整數(shù)數(shù)組這些數(shù)據(jù)結(jié)構(gòu)時(shí),這些結(jié)構(gòu)中專門記錄了元素的個(gè)數(shù)統(tǒng)計(jì)尉辑。

4)晕拆、例外情況,是指某些數(shù)據(jù)結(jié)構(gòu)的特殊記錄材蹬,例如壓縮列表和雙向鏈表都會(huì)記錄表頭和表尾的偏移量实幕。

9、小結(jié)

集合類型的范圍操作堤器,因?yàn)橐闅v底層數(shù)據(jù)結(jié)構(gòu)淳附,復(fù)雜度通常是 O(N)洛姑。這里筐钟,我的建議是:用其他命令來(lái)替代贪磺,例如可以用 SCAN 來(lái)代替,避免在 Redis 內(nèi)部產(chǎn)生費(fèi)時(shí)的全集合遍歷操作辉川。

因地制宜地使用 List 類型表蝙。

10、每課一問:整數(shù)數(shù)組和壓縮列表在查找時(shí)間復(fù)雜度方面并沒有很大的優(yōu)勢(shì)乓旗,那為什么 Redis 還會(huì)把它們作為底層數(shù)據(jù)結(jié)構(gòu)呢府蛇?

1、內(nèi)存利用率屿愚,數(shù)組和壓縮列表都是非常緊湊的數(shù)據(jù)結(jié)構(gòu)汇跨,它比鏈表占用的內(nèi)存要更少。Redis是內(nèi)存數(shù)據(jù)庫(kù)妆距,大量數(shù)據(jù)存到內(nèi)存中穷遂,此時(shí)需要做盡可能的優(yōu)化,提高內(nèi)存的利用率娱据。

2蚪黑、數(shù)組對(duì)CPU高速緩存支持更友好,所以Redis在設(shè)計(jì)時(shí)中剩,集合數(shù)據(jù)元素較少情況下忌穿,默認(rèn)采用內(nèi)存緊湊排列的方式存儲(chǔ),同時(shí)利用CPU高速緩存不會(huì)降低訪問速度咽安。當(dāng)數(shù)據(jù)元素超過(guò)設(shè)定閾值后伴网,避免查詢時(shí)間復(fù)雜度太高蓬推,轉(zhuǎn)為哈希和跳表數(shù)據(jù)結(jié)構(gòu)存儲(chǔ)妆棒,保證查詢效率。

Redis的List底層使用壓縮列表本質(zhì)上是將所有元素緊挨著存儲(chǔ),所以分配的是一塊連續(xù)的內(nèi)存空間糕珊,雖然數(shù)據(jù)結(jié)構(gòu)本身沒有時(shí)間復(fù)雜度的優(yōu)勢(shì)动分,但是這樣節(jié)省空間而且也能避免一些內(nèi)存碎片。


03 | 高性能IO模型:為什么單線程Redis能那么快红选?

1澜公、Redis 是單線程,主要是指 Redis 的網(wǎng)絡(luò) IO和鍵值對(duì)讀寫是由一個(gè)線程來(lái)完成的喇肋,這也是 Redis 對(duì)外提供鍵值存儲(chǔ)服務(wù)的主要流程坟乾。

但 Redis 的其他功能,比如持久化蝶防、異步刪除甚侣、集群數(shù)據(jù)同步等,其實(shí)是由額外的線程執(zhí)行的间学。--------redis不只是單線程

2殷费、多線程開銷--吞吐量問題

增加線程數(shù),吞吐量反而降低-多線程編程模式面臨的共享資源的并發(fā)訪問控制問題-----為什么redis要單線程

3低葫、單線程 Redis 為什么那么快详羡?

一方面采用高效的數(shù)據(jù)結(jié)構(gòu),另一方面采用IO多路復(fù)用機(jī)制嘿悬,使其在網(wǎng)絡(luò) IO 操作中能并發(fā)處理大量的客戶端請(qǐng)求实柠,實(shí)現(xiàn)高吞吐率

4、基本io模型的阻塞點(diǎn)在哪善涨?

單線程依此執(zhí)行下面操作:但是accept(客戶端建立連接)主到、send(向 socket 中寫回?cái)?shù)據(jù))、recv(從 socket 中讀取請(qǐng)求)會(huì)存在阻塞躯概,導(dǎo)致其他客戶端無(wú)法連接

redis基本io模型

5登钥、基于多路復(fù)用的高性能 I/O 模型

Linux 中的 IO 多路復(fù)用機(jī)制是指一個(gè)線程處理多個(gè) IO 流,就是我們經(jīng)常聽到的select/epoll 機(jī)制娶靡。簡(jiǎn)單來(lái)說(shuō)牧牢,在 Redis 只運(yùn)行單線程的情況下,該機(jī)制允許內(nèi)核中姿锭,同時(shí)存在多個(gè)監(jiān)聽套接字和已連接套接字塔鳍。內(nèi)核會(huì)一直監(jiān)聽這些套接字上的連接請(qǐng)求或數(shù)據(jù)請(qǐng)求。一旦有請(qǐng)求到達(dá)呻此,就會(huì)交給 Redis 線程處理轮纫,這就實(shí)現(xiàn)了一個(gè) Redis 線程處理多個(gè)IO 流的效果。

多個(gè) FD 就是剛才所說(shuō)的多個(gè)套接Redis 網(wǎng)絡(luò)框架調(diào)用 epoll 機(jī)制焚鲜,讓內(nèi)核監(jiān)聽這些套接字掌唾。此時(shí)放前,Redis 線程不會(huì)阻塞在某一個(gè)特定的監(jiān)聽或已連接套接字上,也就是說(shuō)糯彬,不會(huì)阻塞在某一個(gè)特定的客戶端請(qǐng)求處理上凭语。正因?yàn)榇耍琑edis 可以同時(shí)和多個(gè)客戶端連接并處理請(qǐng)求撩扒,從而提升并發(fā)性似扔。

基于多路復(fù)用的Redis高性能IO模型

為了在請(qǐng)求到達(dá)時(shí)能通知到 Redis 線程,select/epoll 提供了基于事件的回調(diào)機(jī)制搓谆,即針對(duì)不同事件的發(fā)生炒辉,調(diào)用相應(yīng)的處理函數(shù)

select/epoll 一旦監(jiān)測(cè)到 FD 上有請(qǐng)求到達(dá)時(shí)泉手,就會(huì)觸發(fā)相應(yīng)的事件辆脸,然后這些事件被放入時(shí)間處理器,然后redis單線程對(duì)這個(gè)時(shí)間處理器不斷進(jìn)行處理螃诅。這樣一來(lái)啡氢,Redis 無(wú)需一直輪詢是否有請(qǐng)求實(shí)際發(fā)生,這就可以避免造成 CPU 資源浪費(fèi)术裸。同時(shí)倘是,Redis 在對(duì)事件隊(duì)列中的事件進(jìn)行處理時(shí),會(huì)調(diào)用相應(yīng)的處理函數(shù)袭艺,這就實(shí)現(xiàn)了基于事件的回調(diào)搀崭。因?yàn)?Redis 一直在對(duì)事件隊(duì)列進(jìn)行處理,所以能及時(shí)響應(yīng)客戶端請(qǐng)求猾编,提升Redis 的響應(yīng)性能瘤睹。

這就像病人去醫(yī)院瞧病。在醫(yī)生實(shí)際診斷前答倡,每個(gè)病人(等同于請(qǐng)求)都需要先分診轰传、測(cè)體溫、登記等瘪撇。如果這些工作都由醫(yī)生來(lái)完成获茬,醫(yī)生的工作效率就會(huì)很低。所以倔既,醫(yī)院都設(shè)置了分診臺(tái)恕曲,分診臺(tái)會(huì)一直處理這些診斷前的工作(類似于 Linux 內(nèi)核監(jiān)聽請(qǐng)求),然后再轉(zhuǎn)交給醫(yī)生做實(shí)際診斷渤涌。這樣即使一個(gè)醫(yī)生(相當(dāng)于 Redis 單線程)佩谣,效率也能提升。

6实蓬、小結(jié)

重點(diǎn)學(xué)習(xí)了 Redis 線程的三個(gè)問題:“Redis 真的只有單線程嗎茸俭?”“為什么用單線程吊履?”“單線程為什么這么快?”

Redis 單線程是指它對(duì)網(wǎng)絡(luò) IO 和數(shù)據(jù)讀寫的操作采用了一個(gè)線程瓣履,而采用單線程的一個(gè)核心原因是避免多線程開發(fā)的并發(fā)控制問題。單線程的 Redis 也能獲得高性能练俐,跟多路復(fù)用的 IO 模型密切相關(guān)袖迎,因?yàn)檫@避免了 accept() 和 send()/recv() 潛在的網(wǎng)絡(luò) IO 操作阻塞點(diǎn)。

accept():和客戶端建立連接

send():向socket寫會(huì)數(shù)據(jù)

recv():從socket中讀取請(qǐng)求

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末腺晾,一起剝皮案震驚了整個(gè)濱河市燕锥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌悯蝉,老刑警劉巖归形,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異鼻由,居然都是意外死亡暇榴,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門蕉世,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)蔼紧,“玉大人,你說(shuō)我怎么就攤上這事狠轻〖槔” “怎么了?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵向楼,是天一觀的道長(zhǎng)查吊。 經(jīng)常有香客問我,道長(zhǎng)湖蜕,這世上最難降的妖魔是什么逻卖? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮昭抒,結(jié)果婚禮上箭阶,老公的妹妹穿的比我還像新娘。我一直安慰自己戈鲁,他們只是感情好仇参,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著婆殿,像睡著了一般诈乒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上婆芦,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天怕磨,我揣著相機(jī)與錄音喂饥,去河邊找鬼。 笑死肠鲫,一個(gè)胖子當(dāng)著我的面吹牛员帮,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播导饲,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼捞高,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了渣锦?” 一聲冷哼從身側(cè)響起硝岗,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎袋毙,沒想到半個(gè)月后型檀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡听盖,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年胀溺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片皆看。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡月幌,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出悬蔽,到底是詐尸還是另有隱情扯躺,我是刑警寧澤,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布蝎困,位于F島的核電站录语,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏禾乘。R本人自食惡果不足惜澎埠,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望始藕。 院中可真熱鬧蒲稳,春花似錦、人聲如沸伍派。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)诉植。三九已至祥国,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舌稀。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來(lái)泰國(guó)打工啊犬, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人壁查。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓觉至,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親睡腿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子语御,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容