1. 為什么Redis單線程還這么快?

        共 2548字,需瀏覽 6分鐘

         ·

        2020-09-22 15:00


        眾所周知,Redis在內(nèi)存庫數(shù)據(jù)庫領(lǐng)域非常地火熱,它極高的性能和豐富的數(shù)據(jù)結(jié)構(gòu)為我們的開發(fā)提供了極大的便利。


        但我們也聽說了,Redis是單線程的,為什么采用單線程的Redis也會如此之快呢?這篇文章我們來分析一下其中的緣由。


        其實(shí),嚴(yán)格來說,Redis Server是多線程的,只是它的請求處理整個(gè)流程是單線程處理的。這一點(diǎn)我們一定要清楚了解到,不要單純地認(rèn)為Redis Server是單線程的!


        我們平時(shí)說的Redis單線程快是指它的請求處理過程非常地快!


        下面我們就來分下一下為什么請求處理使用單線程,依舊可以達(dá)到這么高的性能。


        Redis的性能非常之高,每秒可以承受10W+的QPS,它如此優(yōu)秀的性能主要取決于以下幾個(gè)方面:


        • 純內(nèi)存操作
        • 使用IO多路復(fù)用技術(shù)
        • 非CPU密集型任務(wù)
        • 單線程的優(yōu)勢


        純內(nèi)存操作


        Redis是一個(gè)內(nèi)存數(shù)據(jù)庫,它的數(shù)據(jù)都存儲在內(nèi)存中,這意味著我們讀寫數(shù)據(jù)都是在內(nèi)存中完成,這個(gè)速度是非??斓?。


        Redis是一個(gè)KV內(nèi)存數(shù)據(jù)庫,它內(nèi)部構(gòu)建了一個(gè)哈希表,根據(jù)指定的KEY訪問時(shí),只需要O(1)的時(shí)間復(fù)雜度就可以找到對應(yīng)的數(shù)據(jù)。同時(shí),Redis提供了豐富的數(shù)據(jù)類型,并使用高效的操作方式進(jìn)行操作,這些操作都在內(nèi)存中進(jìn)行,并不會大量消耗CPU資源,所以速度極快。


        使用IO多路復(fù)用技術(shù)


        Redis采用單線程,那么它是如何處理多個(gè)客戶端連接請求呢?


        Redis采用了IO多路復(fù)用技術(shù)和非阻塞IO,這個(gè)技術(shù)由操作系統(tǒng)實(shí)現(xiàn)提供,Redis可以方便地操作系統(tǒng)的API即可。Redis可以在單線程中監(jiān)聽多個(gè)Socket的請求,在任意一個(gè)Socket可讀/可寫時(shí),Redis去讀取客戶端請求,在內(nèi)存中操作對應(yīng)的數(shù)據(jù),然后再寫回到Socket中。


        整個(gè)過程非常高效,Redis利用了IO多路復(fù)用技術(shù)的事件驅(qū)動模型,保證在監(jiān)聽多個(gè)Socket連接的情況下,只針對有活動的Socket采取反應(yīng)。


        非CPU密集型任務(wù)


        采用單線程的缺點(diǎn)很明顯,無法使用多核CPU。Redis作者提到,由于Redis的大部分操作并不是CPU密集型任務(wù),而Redis的瓶頸在于內(nèi)存和網(wǎng)絡(luò)帶寬。


        在高并發(fā)請求下,Redis需要更多的內(nèi)存和更高的網(wǎng)絡(luò)帶寬,否則瓶頸很容易出現(xiàn)在內(nèi)存不夠用和網(wǎng)絡(luò)延遲等待的情況。


        當(dāng)然,如果你覺得單個(gè)Redis實(shí)例的性能不足以支撐業(yè)務(wù),Redis作者推薦部署多個(gè)Redis節(jié)點(diǎn),組成集群的方式來利用多核CPU的能力,而不是在單個(gè)實(shí)例上使用多線程來處理。


        單線程的優(yōu)勢


        基于以上特性,Redis采用單線程已足夠達(dá)到非常高的性能,所以Redis沒有采用多線程模型。


        另外,單線程模型還帶了以下好處:


        • 沒有了多線程上下文切換的性能損耗
        • 沒有了訪問共享資源加鎖的性能損耗
        • 開發(fā)和調(diào)試非常友好,可維護(hù)性高


        所以Redis正是基于以上這些方面,所以采用了單線程模型來完成請求處理的工作。


        多線程優(yōu)化


        在文章開頭已經(jīng)特別說明,Redis Server本身是多線程的,除了請求處理流程是單線程處理之外,Redis內(nèi)部還有其他工作線程在后臺執(zhí)行,它負(fù)責(zé)異步執(zhí)行某些比較耗時(shí)的任務(wù),例如AOF每秒刷盤、AOF文件重寫都是在另一個(gè)線程中完成的。


        而在Redis 4.0之后,Redis引入了lazyfree的機(jī)制,提供了unlink、flushall aysc、flushdb async等命令和lazyfree-lazy-eviction、lazyfree-lazy-expire等機(jī)制來異步釋放內(nèi)存,它主要是為了解決在釋放大內(nèi)存數(shù)據(jù)導(dǎo)致整個(gè)redis阻塞的性能問題。


        在刪除大key時(shí),釋放內(nèi)存往往都比較耗時(shí),所以Redis提供異步釋放內(nèi)存的方式,讓這些耗時(shí)的操作放到另一個(gè)線程中異步去處理,從而不影響主線程的執(zhí)行,提高性能。


        到了Redis 6.0,Redis又引入了多線程來完成請求數(shù)據(jù)的協(xié)議解析,進(jìn)一步提升性能。


        它主要是解決高并發(fā)場景下,單線程解析請求數(shù)據(jù)協(xié)議帶來的壓力。請求數(shù)據(jù)的協(xié)議解析由多線程完成之后,后面的請求處理階段依舊還是單線程排隊(duì)處理。


        可見,Redis并不是保守地認(rèn)為單線程有多好,也不是為了使用多線程而引入多線程。Redis作者很清楚單線程和多線程的使用場景,針對性地優(yōu)化,這是非常值得我們學(xué)習(xí)的。


        缺點(diǎn)


        上面介紹了單線程可以達(dá)到如此高的性能,并不是說它就沒有缺點(diǎn)了。


        單線程處理最大的缺點(diǎn)就是,如果前一個(gè)請求發(fā)生耗時(shí)比較久的操作,那么整個(gè)Redis就會阻塞住,其他請求也無法進(jìn)來,直到這個(gè)耗時(shí)久的操作處理完成并返回,其他請求才能被處理到。


        我們平時(shí)遇到Redis變慢或長時(shí)間阻塞的問題,90%也都是因?yàn)镽edis處理請求是單線程這個(gè)原因?qū)е碌摹?/p>


        所以,我們在使用Redis時(shí),一定要避免非常耗時(shí)的操作,例如使用時(shí)間復(fù)雜度過高的方式獲取數(shù)據(jù)、一次性獲取過多的數(shù)據(jù)、大量key集中過期導(dǎo)致Redis淘汰key壓力變大等等,這些場景都會阻塞住整個(gè)處理線程,直到它們處理完成,勢必會影響業(yè)務(wù)的訪問。


        我會在后期的文章中專門介紹具體有哪些場景會引發(fā)Redis阻塞的問題,并提供規(guī)避問題的方法和優(yōu)化方案。


        總結(jié)


        Redis使用單線程,配合IO多路復(fù)用技術(shù),可以完成多個(gè)連接的請求處理。而且正是由于它的使用定位是內(nèi)存數(shù)據(jù)庫,這樣幾乎所有的操作都在內(nèi)存中完成,它的性能可以達(dá)到非常之高。


        同時(shí),單線程沒有了線程上下文切換和訪問共享資源加鎖的性能損耗,而且單線程模型對程序的開發(fā)和調(diào)試非常友好,因此Redis使用單線程模型也就在情理之中了。


        Redis在最近的版本也對多線程進(jìn)行了優(yōu)化,用于解決釋放大內(nèi)存數(shù)據(jù)和請求數(shù)據(jù)協(xié)議解析對Redis產(chǎn)生的性能影響,進(jìn)一步提升了Redis的性能。


        單線程結(jié)合上述場景可以達(dá)到非常高的性能,同時(shí)也存在耗時(shí)操作阻塞整個(gè)線程的問題,我們在使用Redis時(shí)要避免耗時(shí)過長的操作,才能更好地發(fā)揮Redis的性能。


        原文鏈接:kaito-kidd.com/2020/06/28/why-redis-so-fast/




        瀏覽 56
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評論
        圖片
        表情
        推薦
        點(diǎn)贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 插插插天天| 日韩一级免费黄片 | 99视频免费在线观看 | 亚洲日本中文 | 亚洲春色综合另类校园电影 |