最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

聊聊單線程的Redis為何會快到飛起

 更新時間:2022年02月24日 14:41:06   作者:小王曾是少年  
Redis想必大家都或多或少聽過吧,我們在工作學(xué)習(xí)中通常用它來作為緩存使用,既然是作為緩存,大家的第一反應(yīng)肯定是:這家伙很快

實際上它確實也很快 : ),但Redis底層卻是單線程的!有同學(xué)可能就要有疑問了,為什么單線程的Redis卻能夠快到飛起?

別急,我盡量用通俗易懂的語言來給各位說道說道~~

Redis是單線程,主要是指Redis的網(wǎng)絡(luò)IO和讀寫是由一個線程來完成的,但Redis的其他功能,比如持久化、異步刪除、集群數(shù)據(jù)同步等,其實是由額外的線程執(zhí)行的。這不是本文討論的重點,有個印象即可

Redis為什么用單線程?

多線程的開銷

通常情況下,在采用多線程后,如果沒有良好的系統(tǒng)設(shè)計,其實是右圖所展示的那樣(注意縱坐標)。剛開始增加線程數(shù)時,系統(tǒng)吞吐率會增加,再進一步增加線程時,系統(tǒng)吞吐率就增長遲緩了,甚至還會出現(xiàn)下降的情況。

關(guān)鍵瓶頸在于: 系統(tǒng)中通常會存在會被多線程同時訪問的共享資源,為了保證共享資源的正確性,就需要有額外的機制保證線程安全性,例如加鎖,這會帶來額外的開銷。

比如拿最常用的List類型來舉例吧,假設(shè)Redis采用多線程設(shè)計,有兩個線程A和B分別對ListLPUSHLPUSH操作,為了使得每次執(zhí)行都是相同的結(jié)果,即【B線程取出A線程放入的數(shù)據(jù)】就需要讓這兩個過程串行執(zhí)行。這就是多線程編程模式面臨的共享資源的并發(fā)訪問控制問題。

并發(fā)訪問控制一直是多線程開發(fā)中的一個難點問題:如果只是簡單地采用一個互斥鎖,就會出現(xiàn)即使增加了線程,大部分線程也在等待獲取互斥鎖,并行變串行,系統(tǒng)吞吐率并沒有隨著線程的增加而增加。

同時加入并發(fā)訪問控制后也會降低系統(tǒng)代碼的可讀性和可維護性,所以Redis干脆直接采用了單線程模式。

Redis使用單線程為什么還這么快?

之所以使用單線程是Redis設(shè)計者多方面衡量的結(jié)果。

  • Redis的大部分操作在內(nèi)存上完成
  • 采用了高效的數(shù)據(jù)結(jié)構(gòu),例如哈希表和跳表
  • 采用了多路復(fù)用機制,使其在網(wǎng)絡(luò)IO操作中能并發(fā)處理大量的客戶端請求,實現(xiàn)高吞吐率

既然Redis使用單線程進行IO,如果線程被阻塞了就無法進行多路復(fù)用了,所以不難想象,Redis肯定還針對網(wǎng)絡(luò)和IO操作的潛在阻塞點進行了設(shè)計。

網(wǎng)絡(luò)與IO操作的潛在阻塞點

在網(wǎng)絡(luò)通信里,服務(wù)器為了處理一個Get請求,需要監(jiān)聽客戶端請求(bind/listen),和客戶端建立連接(accept),從socket中讀取請求(recv),解析客戶端發(fā)送請求(parse),最后給客戶端返回結(jié)果(send)。

最基本的一種單線程實現(xiàn)是依次執(zhí)行上面的操作。

上面標紅的accept和recv操作都是潛在的阻塞點:

  • 當Redis監(jiān)聽到有連接請求,但卻一直不能成功建立起連接時,就會阻塞在accept()函數(shù)這里,其他客戶端此時也無法和Redis建立連接
  • 當Redis通過recv()從一個客戶端讀取數(shù)據(jù)時,如果數(shù)據(jù)一直沒有到達,也會一直阻塞

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

為了解決IO中的阻塞問題,Redis采用了Linux的IO多路復(fù)用機制,該機制允許內(nèi)核中,同時存在多個監(jiān)聽套接字和已連接套接字(select/epoll)。

內(nèi)核會一直監(jiān)聽這些套接字上的連接或數(shù)據(jù)請求。一旦有請求到達,就會交給Redis處理,這就實現(xiàn)了一個Redis線程處理多個IO流的效果。

此時,Redis線程就不會阻塞在某一個特定的客戶端請求處理上,所以它可以同時和多個客戶端連接并處理請求。

回調(diào)機制

select/epoll一旦監(jiān)測到FD上有請求到達時,就會觸發(fā)相應(yīng)的事件被放進一個隊列里,Redis線程對該事件隊列不斷進行處理,所以就實現(xiàn)了基于事件的回調(diào)。

例如,Redis會對Accept和Read事件注冊acceptget回調(diào)函數(shù)。當Linux內(nèi)核監(jiān)聽到有連接請求或讀數(shù)據(jù)請求時,就會觸發(fā)Accept事件和Read事件,此時,內(nèi)核就會回調(diào)Redis相應(yīng)的acceptget函數(shù)進行處理。

Redis的性能瓶頸點

經(jīng)過上面的分析,雖然通過多路復(fù)用機制可以同時監(jiān)聽多個客戶端的請求,但Redis仍然有一些性能瓶頸點,這也是我們平時編程需要極力避免的情況。

1. 耗時操作

任意一個請求在Redis中一旦耗時較久,都會影響整個server的性能。后面的請求都要等前面這個耗時請求處理完成,自己才能被處理到。

這一點需要我們在設(shè)計業(yè)務(wù)場景時去規(guī)避;Redis的lazy-free機制也把釋放內(nèi)存的耗時操作放在了異步線程中去執(zhí)行了。

2. 高并發(fā)場景

并發(fā)量非常大時,單線程讀寫客戶端IO數(shù)據(jù)存在性能瓶頸,雖然采用IO多路復(fù)用機制,但還是只能單線程依次讀取客戶端的數(shù)據(jù),無法利用到CPU多核。

Redis在6.0可以利用CPU多核多線程讀寫客戶端數(shù)據(jù),但只是針對客戶端的讀寫是并行的,每個命令的真正操作還是單線程。

其他Redis相關(guān)的有趣問題

借此機會也提幾個和redis相關(guān)的有意思的問題。

  • 為什么要用Redis,直接訪問內(nèi)存不好嗎?

這一條其實并沒有很明確的界定,對于一些不經(jīng)常變動的數(shù)據(jù),可以直接放到內(nèi)存里,不一定要放到Redis里,可以放到內(nèi)存里。一致性問題:如果一個數(shù)據(jù)被修改了,數(shù)據(jù)在本地內(nèi)存里的話,可能只有一臺服務(wù)器上的數(shù)據(jù)被修改了。如果用Redis里面的話,我們訪問Redis服務(wù)器,可以解決一致性問題。

  • 數(shù)據(jù)太多內(nèi)存放不下怎么辦?比如我要緩存100G的數(shù)據(jù),怎么辦?

這里也要打一個廣告Tair是淘寶開源的分布式KV緩存系統(tǒng),它從Redis繼承了豐富的操作,理論上總數(shù)據(jù)量無限制,針對可用性、可擴展性、可靠性也進行了升級,感興趣的小伙伴們可以了解一下~

到此這篇關(guān)于聊聊單線程的Redis為何會快到飛起的文章就介紹到這了,更多相關(guān)Java Redis內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • http basic authentication通過post方式訪問api示例分享 basic認證示例

    http basic authentication通過post方式訪問api示例分享 basic認證示例

    在HTTP中,基本認證是一種用來允許Web瀏覽器或其他客戶端程序在請求時提供以用戶名和口令形式的憑證,這篇文章主要介紹了http basic authentication通過post方式訪問api示例,大家參考使用吧
    2014-01-01
  • 淺談SpringBoot如何封裝統(tǒng)一響應(yīng)體

    淺談SpringBoot如何封裝統(tǒng)一響應(yīng)體

    今天帶各位小伙伴學(xué)習(xí)SpringBoot如何封裝統(tǒng)一響應(yīng)體,文中有非常詳細的介紹及代碼示例,對正在學(xué)習(xí)java的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-05-05
  • 淺談Java讀寫注冊表的方式Preferences與jRegistry

    淺談Java讀寫注冊表的方式Preferences與jRegistry

    這篇文章主要介紹了淺談Java讀寫注冊表的方式Preferences與jRegistry,分享了相關(guān)代碼示例,小編覺得還是挺不錯的,具有一定借鑒價值,需要的朋友可以參考下
    2018-02-02
  • Java String不可變性實現(xiàn)原理解析

    Java String不可變性實現(xiàn)原理解析

    這篇文章主要介紹了Java String不可變性實現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • Java中Map遍歷的九種方式匯總

    Java中Map遍歷的九種方式匯總

    這篇文章主要介紹了Java中九種?Map?的遍歷方式匯總的相關(guān)資料,需要的朋友可以參考下
    2022-11-11
  • SpringBoot實現(xiàn)過濾器Filter的三種方式

    SpringBoot實現(xiàn)過濾器Filter的三種方式

    過濾器Filter由Servlet提供,基于函數(shù)回調(diào)實現(xiàn)鏈式對網(wǎng)絡(luò)請求與響應(yīng)的攔截與修改,本文講給大家詳細介紹SpringBoot實現(xiàn)過濾器Filter的三種方式,需要的朋友可以參考下
    2023-08-08
  • Java中this關(guān)鍵字的用法詳解

    Java中this關(guān)鍵字的用法詳解

    我知道很多朋友都和我一樣,在JAVA程序中似乎經(jīng)常見到this,自己也偶爾用到它,但是到底this該怎么用,卻心中無數(shù),下面這篇文章主要給大家介紹了關(guān)于Java中this關(guān)鍵字用法的相關(guān)資料,需要的朋友可以參考下
    2023-05-05
  • 詳解SpringCloud的負載均衡

    詳解SpringCloud的負載均衡

    這篇文章主要介紹了SpringCloud的負載均衡的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)使用SpringCloud,感興趣的朋友可以了解下
    2021-03-03
  • java實現(xiàn)單鏈表、雙向鏈表

    java實現(xiàn)單鏈表、雙向鏈表

    這篇文章主要為大家詳細介紹了java實現(xiàn)單鏈表、雙向鏈表的相關(guān)資料,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-03-03
  • Spring三級緩存解決循環(huán)依賴的過程分析

    Spring三級緩存解決循環(huán)依賴的過程分析

    這篇文章主要介紹了Spring三級緩存解決循環(huán)依賴,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04

最新評論

阿坝| 孟津县| 吉林市| 沛县| 柘城县| 信丰县| 临泽县| 微山县| 铜山县| 黄冈市| 会同县| 筠连县| 临夏县| 盐边县| 兰西县| 漯河市| 正镶白旗| 博湖县| 淮北市| 北辰区| 全南县| 桂东县| 桦南县| 冕宁县| 泰安市| 阳春市| 台中市| 玉溪市| 家居| 和政县| 浙江省| 罗平县| 南澳县| 忻城县| 麟游县| 怀柔区| 南乐县| 神木县| 沂南县| 肥西县| 汤原县|