Redis背后的神奇力量:為何它如此高效?
Redis的速度快主要有以下幾個原因:
圖片
1、基于內(nèi)存操作
Redis的操作都是基于內(nèi)存的,數(shù)據(jù)存儲在內(nèi)存中,而內(nèi)存的讀寫速度遠(yuǎn)遠(yuǎn)快于硬盤,內(nèi)存的運(yùn)行速度比硬盤高出幾個數(shù)量級,就像從翻閱書籍變成即刻在線信息查詢,訪問時間大幅縮短。
圖片
p.s.CrystalDiskMark測試不了內(nèi)存,所以使用其它工具測試內(nèi)存,雖然測試方式及緯度不同,但結(jié)果還是可以參考看的。
機(jī)械硬盤、固態(tài)硬盤及內(nèi)存的讀寫速度有以下對比:
- 機(jī)械硬盤:機(jī)械硬盤的讀寫速度相對較慢,通常在100 MB/s到200 MB/s之間,具體取決于磁盤的轉(zhuǎn)速和技術(shù)規(guī)格。
- 固態(tài)硬盤:固態(tài)硬盤的讀寫速度遠(yuǎn)遠(yuǎn)快于機(jī)械硬盤。一般而言,SSD的讀速度可以達(dá)到數(shù)百 MB/s至數(shù)千 MB/s,而寫速度也在同樣的范圍內(nèi)。
- 內(nèi)存: 內(nèi)存的讀寫速度遠(yuǎn)遠(yuǎn)超過硬盤,通常在GB/s級別。內(nèi)存讀寫速度可以達(dá)到幾千 MB/s,甚至更高。
當(dāng)然在Redis官網(wǎng)還提到了“Redis on Flash”
官方文檔:
圖片
"Redis on Flash" 是指將 Redis 數(shù)據(jù)存儲在閃存(Flash Storage)上,而不是傳統(tǒng)的隨機(jī)訪問存儲器(RAM)上。這種做法通常被用于處理大規(guī)模的數(shù)據(jù)集,因?yàn)殚W存的存儲容量通常比RAM大得多。
2、單線程模型
官方文檔:
圖片
圖片
可以看到官方文檔:1、Redis的單線程特性2、Redis 的性能瓶頸通常出現(xiàn)在內(nèi)存或網(wǎng)絡(luò)方面,而不是 CPU 方面。
雖然 Redis 官方 FAQ 沒有明確解釋 Redis 單線程設(shè)計(jì)的原因,但確實(shí)在文檔中指出 Redis 的性能瓶頸通常出現(xiàn)在內(nèi)存或網(wǎng)絡(luò)方面,而不是 CPU 方面。
Redis的工作負(fù)載主要涉及內(nèi)存操作和網(wǎng)絡(luò)通信,而不是 CPU 密集型計(jì)算,因此 CPU 通常并不是 Redis 性能的瓶頸。在大多數(shù)情況下,性能瓶頸可能更多地出現(xiàn)在內(nèi)存訪問速度或網(wǎng)絡(luò)帶寬上,這也是 Redis 在內(nèi)存和網(wǎng)絡(luò)方面進(jìn)行優(yōu)化的原因。
Redis的主線程是單線程的,所有操作都得按順序執(zhí)行,避免了多線程帶來的額外開銷和復(fù)雜性。 這種設(shè)計(jì)使得 Redis 在處理許多短期和高頻的讀寫操作時非常高效,特別適合緩存和實(shí)時數(shù)據(jù)存儲的應(yīng)用場景。總結(jié)以下幾點(diǎn):
- Redis的工作負(fù)載主要涉及內(nèi)存操作和網(wǎng)絡(luò)通信,而不是 CPU 密集型計(jì)算,因此 CPU 通常并不是 Redis 性能的瓶頸。
- Redis 的大部分操作都是對內(nèi)存的讀寫操作,這些操作的速度非??臁6嗑€程模型可以提高并發(fā)性,但對于內(nèi)存操作,并發(fā)性并不重要。
- 多線程模型會帶來額外的開銷和復(fù)雜性。例如,多線程需要進(jìn)行線程調(diào)度、線程同步等操作,這些操作會占用 CPU 資源,并增加程序的復(fù)雜性。
3、I/O多路復(fù)用技術(shù)
官方文檔:
圖片
圖片
可以看到Redis官方文檔多處提到的“multiplexing and non-blocking I/O”。那么什么是multiplexing and non-blocking I/O呢?I/O 多路復(fù)用技術(shù)是指一個線程可以同時監(jiān)視多個I/O)操作。當(dāng)某個 I/O 操作就緒時,操作系統(tǒng)會通知該線程。
I/O 多路復(fù)用技術(shù)可以有效地提高 I/O 效率。傳統(tǒng)的 I/O 模型中,一個線程只能執(zhí)行一個 I/O 操作。當(dāng)該 I/O 操作阻塞時,該進(jìn)程或線程將無法執(zhí)行其他操作,這會導(dǎo)致 CPU 資源的浪費(fèi)。
Redis采用I/O多路復(fù)用技術(shù),并發(fā)處理連接,使得整個過程只在調(diào)用select、poll、epoll這些調(diào)用的時候才會阻塞,收發(fā)客戶消息是不會阻塞的,整個進(jìn)程或者線程就被充分利用起來。
如果以上說明看著費(fèi)力可以看看以下內(nèi)容:
I/O多路復(fù)用=餐廳服務(wù)員記錄訂單
假設(shè)一家忙碌的餐廳服務(wù)員,負(fù)責(zé)接待顧客點(diǎn)餐和為他們服務(wù)。如果每次只能處理一個桌子的訂單,那就太浪費(fèi)時間了?如果同時處理多個桌子的訂單,先把每個桌子上的點(diǎn)餐需求一個個記在心里,然后再去后廚逐個去處理。當(dāng)有一個桌子的顧客在思考菜單時,你可以去另一個桌子送菜,再回來接著處理點(diǎn)餐。這樣,你可以在等待一個桌子的訂單時,同時為其他桌子服務(wù),提高了效率。
4、高效的數(shù)據(jù)結(jié)構(gòu)
Redis使用了高效的數(shù)據(jù)結(jié)構(gòu),如簡單動態(tài)字符串、壓縮列表、跳躍表等,這些數(shù)據(jù)結(jié)構(gòu)為了追求更快的速度。
簡單動態(tài)字符串(SDS):
SDS 是 Redis 中用來表示字符串的數(shù)據(jù)結(jié)構(gòu)。它是一種動態(tài)調(diào)整大小的字符串類型,可以高效地進(jìn)行字符串的追加、刪除和修改操作。
SDS 在內(nèi)部包含字符串長度信息,使得獲取字符串長度的操作更為高效。而且,SDS 的空間分配策略和惰性空間釋放使得對字符串的修改操作更加迅速。
壓縮列表:
壓縮列表是一種用于存儲列表數(shù)據(jù)的緊湊數(shù)據(jù)結(jié)構(gòu)。它可以在節(jié)約內(nèi)存的同時,提供對列表元素的快速訪問。壓縮列表會根據(jù)元素的大小動態(tài)地調(diào)整內(nèi)存占用。
壓縮列表采用了靈活的內(nèi)存布局,可以存儲不同類型的元素,并在某些情況下采用整數(shù)編碼,進(jìn)一步減小存儲空間。
跳躍表:
跳躍表是一種有序的數(shù)據(jù)結(jié)構(gòu),用于實(shí)現(xiàn)有序集合和有序映射。它通過層級的鏈表結(jié)構(gòu),實(shí)現(xiàn)了快速的元素查找、插入和刪除。
跳躍表通過在多個層次上建立索引,可以在O(log N)的時間內(nèi)完成查找等操作,其中 N 是元素的數(shù)量。它是一種高效的有序數(shù)據(jù)結(jié)構(gòu),相較于平衡樹,跳躍表的實(shí)現(xiàn)更加簡單。
5、額外優(yōu)化
Redis 通過數(shù)據(jù)壓縮、惰性加載(僅在需要時加載數(shù)據(jù))、內(nèi)存淘汰(主動清除鮮少使用的數(shù)據(jù)釋放空間)等技術(shù)進(jìn)一步提升速度。這些精細(xì)的調(diào)優(yōu)措施促成一個運(yùn)轉(zhuǎn)順暢、反應(yīng)靈敏的系統(tǒng)。


























