既然redis是單線程模型,怎麼會出現併發訪問操作同一份數據?

林色芬


Redis是單線程模型,這是眾所周知的,這也是它被稱為快man的原因,按照官方的解釋,其是基於內存的採用的是單進程單線程模型,可以達到100000+的QPS,也就是每秒內查詢次數值。


由於Redis採用單線程,避免了不必要的上下文切換和競爭條件,也就代表了它內部是不存在加鎖和釋放鎖等操作的,但對於單線程的定義,實際上只是表示,在一次完整的Redis請求中,有一部分是單線程的,簡單的說,一次完整的Redis請求,一般是從客戶端請求服務器->Redis讀寫事件->Redis處理數據->返回數據,其中的Redis處理數據這一塊,是Redis模型中單線程的體現,但由於Redis同時還是基於多路I/O複用模型的IO流,也就是說會出現多個網絡連接複用請求同一個線程,這也是為了它可以在單線程中高效的處理多個客戶端的連接請求。


這種情況的出現,也就代表了併發的出現。


題幹所述的,併發訪問操作同一份數據,要知道Redis在處理併發的時候,是將多個操作一股腦的塞入一個隊列中,再逐個進行處理,從而看起來是實現了併發,這不違背它單線程的基本模型,但這種併發的處理,會導致操作的順序可能會出現亂序,從而導致最終的結果不正確。


所以高併發情況還是會在邏輯方面進行加鎖,像科普比較多的秒殺啊限流啊啥的,一般是使用Redis的setnx、getset、time來實現分佈式鎖。


有關Redis鎖的問題,可以看本CURD資深程序員的另一個回答(哈哈哈)

如何利用Redis鎖解決高併發問題?


——沒事待在家裡不出門的 居家程序員。(我不想脫髮!)

居家程序員


Redis對於許多同學來說並不陌生,我們的項目中或多或少都會使用到它,特別是大型網站它就是標配的技術選型,再如秒殺系統都會用到Redis數據庫。

Redis是什麼類型的數據庫?

Redis是使用C語言開發的Key-Value數據庫,而且支持數據持久化存儲,數據類型豐富(String、List、Hash、Set、ZSet),針對不同的開發語言都提供了對應的API以便操作。

Redis為什麼是單線程的?

Redis是純內存型數據庫,據說每秒支持10W+ QPS !為啥Redis的性能如此之高呢?這和它的實現機制是分不開的。

首先Redis是內存型數據庫,讀寫數據不會受到硬盤I/O速度限制;另外它採用的是單線程,避免了不必要的上下文切換及競爭,也不存在多線程切換帶來的性能消耗。

Redis客戶端請求是存在併發的

雖說Redis是單線程的,但是作為內存型數據庫,它會有很多客戶端連接服務端進行操作,客戶端之間是存在併發和資源競爭的,多個客戶端操作同一份數據是完全正常的現象。

Redis的併發請求也會帶來一系列問題,比如:緩存擊穿、緩存雪崩、數據一致性問題,但這些問題都是可以解決的。


Redis支持數據的快速讀寫,支持IO多路複用,非阻塞的方式使得其吞吐能力強,總體來說它是十分優秀的一款NoSQL數據庫。

以上就是我的觀點,對於這個問題大家是怎麼看待的呢?歡迎在下方評論區交流 ~ 我是科技領域創作者,十年互聯網從業經驗,歡迎關注我瞭解更多科技知識!

網絡圈


樓主想問的應該是隻有一個線程,如何處理那麼多併發的網絡請求,答案是,是多路複用io。

如果按照基本的寫法tcp連接調用recv會阻塞,單線程程序就沒法再accept,也沒法阻塞在多個recv上所有就只能處理一個tcp連接。有的教材會告訴你,每個連接用一個recv去處理。這個應該是樓主疑惑的點,

但是其實但凡需求高併發的程序都不會用一個線程處理一個連接的寫法,取而代之會使用諸如epoll(Linux特有)一類的多路複用io函數,此時線程不會再阻塞在recv accept上,取而代之線程阻塞在epoll上,epoll管理所有的連接,當epoll返回時,你能拿到所有有數據的連接,一個循環把所有有數據的連接處理了,繼續阻塞到epoll,如此循環,,,,,

樓主問的是個很好的問題,但是這個問題很大,這裡只是最簡單的回答一個點,希望能幫到你


ASRay小鋒


我記得是不會出現併發競爭的吧,難道我記錯了?


分享到:


相關文章: