亚洲最大看欧美片,亚洲图揄拍自拍另类图片,欧美精品v国产精品v呦,日本在线精品视频免费

  • 站長資訊網(wǎng)
    最全最豐富的資訊網(wǎng)站

    redis是單線程還是多線程,為什么

    Redis4.0之前是單線程運行的;Redis4.0后開始支持多線程。Redis4.0之前使用單線程的原因:1、單線程模式方便開發(fā)和調(diào)試;2、Redis內(nèi)部使用了基于epoll的多路復用;3、Redis主要的性能瓶頸是內(nèi)存或網(wǎng)絡帶寬。

    redis是單線程還是多線程,為什么

    (學習視頻分享:redis視頻教程)

    不同版本的Redis是不同的,在Redis4.0之前,Redis是單線程運行的,但單線程并不代表效率低,像Nginx、Nodejs也是單線程程序,但是它們的效率并不低。

    原因是Redis是基于內(nèi)存的,它的瓶頸在于機器的內(nèi)存、網(wǎng)絡帶寬,而不是CPU,在CPU還沒達到瓶頸時機器內(nèi)存可能就滿了、或者帶寬達到瓶頸了。因此CPU不是主要原因,那么自然就采用單線程了,況且使用多線程比較麻煩。

    但是在Redis4.0的時候,已經(jīng)開始支持多線程了,比如后臺刪除等功能。

    簡單來說,Redis在4.0之前使用單線程的模式是因為以下三個原因:

    • 使用單線程模式的Redis,其開發(fā)和維護更簡單,因為單線程模式方便開發(fā)和調(diào)試。

    • 即使使用單線程模型也能夠并發(fā)地處理多客戶端的請求,主要是因為Redis內(nèi)部使用了基于epoll的多路復用。

    • 對于Redis來說,主要的性能瓶頸是內(nèi)存或網(wǎng)絡帶寬,而非CPU。

    但Redis在4.0以及之后的版本中引入了惰性刪除(也叫異步刪除),意思就是我們可以使用異步的方式對Redis中的數(shù)據(jù)進行刪除操作,例如:

    • unlink key:和del key類似,刪除指定的key,若key不存在則key被跳過。但是del會產(chǎn)生阻塞,而unlink命令會在另一個線程中回收內(nèi)存,即它是非阻塞的【http://www.redis.cn/commands/unlink.html】;

    • flushdb async:刪除當前數(shù)據(jù)庫的所有數(shù)據(jù)【http://www.redis.cn/commands/flushdb.html】;

    • flushall async:刪除所有庫中的數(shù)據(jù)【http://www.redis.cn/commands/flushall.html】。

    這樣處理的好處是不會使Redis的主線程卡頓,會把這些操作交給后臺線程來執(zhí)行。

    【通常情況下使用del指令可以很快的刪除數(shù)據(jù),但是當被刪除的key是一個非常大的對象時,例如:刪除的時包含成千上萬個元素的hash集合時,那么del指令就會造成Redis主線程卡頓,因此使用惰性刪除可以有效避免Redis卡頓問題?!?/p>

    考點分析:

    關于Redis線程模型的問題(單線程或多線程)幾乎是Redis必問的問題之一,但回答好的人卻不多,大部分只能回答上來Redis是單線程的以及說出來單線程的眾多好處,但對于Redis4.0和Redis6.0中,尤其是Redis6.0中多線程的特點,能夠準確回答上來的人非常少。關于單線程和多線程的相關知識,還有以下面試題。

    1.Redis主線程既然是單線程,為什么還這個快?

    2.介紹一下Redis中的IO多路復用?

    3.介紹一下Redis6.0中的多線程?

    1.Redis為什么這么快?

    原因有以下幾點:

    a.基于內(nèi)存操作:Redis的所有數(shù)據(jù)都存在內(nèi)存中,因此所有的運算都是內(nèi)存級別的,所以它的性能比較高。

    b.數(shù)據(jù)結(jié)構簡單:Redis的數(shù)據(jù)結(jié)構比較簡單,是為Redis專門設計的,而這些簡單的數(shù)據(jù)結(jié)構的查找和操作的時間復雜度都是O(1)。

    c.多路復用和非阻塞IO:Redis使用IO多路復用功能來監(jiān)聽多個socket連接的客戶端,這樣就可以使用一個線程來處理多個情況,從而減少線程切換帶來的開銷,同時也避免了IO阻塞操作,從而大大提高了Redis的性能。

    d.避免上下文切換:因為是單線程模型,因此就避免了不必要的上下文切換和多線程競爭,這就省去了多線程切換帶來的時間和性能上的開銷,而且單線程不會導致死鎖的問題發(fā)生。

    官方使用的基準測試結(jié)果表明,單線程的Redis可以達到10W/S的吞吐量。

    2.IO多路復用是什么?

    套接字的讀寫方法默認是阻塞的,例如當調(diào)用讀取操作read方法時,緩沖區(qū)沒有任何數(shù)據(jù),那么這個線程會卡在這里,直到緩沖區(qū)有數(shù)據(jù)或者連接被關閉時,read方法才會返回,該線程才能繼續(xù)處理其他業(yè)務。

    但這樣顯然就降低了程序的執(zhí)行效率,而Redis使用的時非阻塞的IO,這就意味著IO的讀寫流程不再是阻塞的,讀寫方法都是瞬間完成并且返回的,也就是它會采用能讀多少就讀多少、能寫多少就寫多少的策略來執(zhí)行IO操作,這顯然更符合我們對性能的追求。

    但這種非阻塞的IO也面臨一個問題,那就是當我們執(zhí)行讀取操作時,有可能只讀取了一部分數(shù)據(jù);同理寫數(shù)據(jù)也是這種情況,當緩沖區(qū)滿了,而我們的數(shù)據(jù)還沒有寫完,那么生效的數(shù)據(jù)何時寫就成了一個問題。

    而IO的多路復用就是解決上面的這個問題的,使用IO多路復用最簡單的方式就是使用select函數(shù),此函數(shù)是操作系統(tǒng)提供給用戶程序的API接口,用于監(jiān)控多個文件描述符的可讀和可寫情況的,這樣就可以監(jiān)控到文件描述符的讀寫事件了。當監(jiān)控到相應的時間之后就可以通知線程處理相應的業(yè)務了,這樣就保證了Redis讀寫功能的正常執(zhí)行。

    【不過現(xiàn)在的操作系統(tǒng)已經(jīng)基本上不適用select函數(shù)了,改為調(diào)用epoll函數(shù)(Linux)了,macOS則是使用Kqueue(繼承與Unix),因為select函數(shù)在文件描述符非常多的時候性能非常差?!?/p>

    3.Redis6.0中的多線程?

    Redis單線程的優(yōu)點非常,不但降低了Redis內(nèi)部實現(xiàn)的負責性,也讓所有操作都可以在無鎖的情況下進行,并且不存在死鎖和線程切換帶來的性能以及時間上的消耗;但是其缺點也很明顯,單線程機制導致Redis的QPS(Query Per Second,每秒查詢數(shù))很難得到有效的提高(雖然夠快了,但人畢竟還是要有更高的追求的)。

    Redis在4.0版本中雖然引入了多線程,但是此版本的多線程只能用于大數(shù)據(jù)量的異步刪除,對于非刪除操作的意義并不是很大。

    如果我們使用Redis多線程就可以分攤Redis同步讀寫IO的壓力,以及充分利用多核CPU資源,并且可以有效的提升Redis的QPS。在Redis中雖然使用了IO多路復用,并且是基于非阻塞的IO進行操作的,但是IO的讀寫本身是阻塞的。比如當socket中有數(shù)據(jù)時,Redis會先將數(shù)據(jù)從內(nèi)核態(tài)空間拷貝到用戶態(tài)空間,然后再進行相關操作,而這個拷貝過程是阻塞的,并且當數(shù)據(jù)量越大時拷貝所需要的的時間就越多,而這些操作都是基于單線程完成的。

    因此在Redis6.0中新增了多線程的功能來提高IO的讀寫性能,它的主要實現(xiàn)思路是將主線程的IO讀寫任務拆分給一組獨立的線程去執(zhí)行,這樣就可以使用多個socket的讀寫并行化了,但Redis的命令依舊是主線程串行執(zhí)行的。

    但是注意:Redis6.0是默認禁用多線程的,但可以通過配置文件redis.conf中的io-threads-do-reads 等于 true 來開啟。但是還不夠,除此之外我們還需要設置線程的數(shù)量才能正確地開啟多線程的功能,同樣是修改Redis的配置,例如設置 io-threads 4,表示開啟4個線程。

    【關于線程數(shù)的設置,官方的建議是如果為4核CPU,那么設置線程數(shù)為2或3;如果為8核CPU,那么設置線程數(shù)為6.總之線程數(shù)一定要小于機器的CPU核數(shù),線程數(shù)并不是越大越好?!?/p>

    關于Redis的性能,Redis的作者在2019年的RedisConf大會上提到,Redis6.0引入的多線程IO特性對性能的提升至少是一倍以上。國人也有在阿里云使用4個線程的Redis版本和單線程的Redis進行比較測試,發(fā)現(xiàn)測試結(jié)果和Redis作者說的一致,性能基本可以提高一倍。

    總結(jié):

    本文介紹了Redis在4.0之前單線程依然快的原因:基于內(nèi)存操作、數(shù)據(jù)結(jié)構簡單、IO多路復用和非阻塞IO、避免了不必要的線程上下文切換。并且在Redis4.0開始支持多線程,主要體現(xiàn)在大數(shù)據(jù)的異步刪除方面,例如:unlink key、flushdb async、flushall async等。而Redis6.0的多線程則增加了對IO讀寫的并發(fā)能力,用于更好的提升Redis的性能。

    贊(0)
    分享到: 更多 (0)
    網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號