03.07 Redis為何設計為單線程?

藍風


redis的一個特點是讀寫速度快,這就很容易讓人誤以為redis是多線程的。因為大家想當然的會認為多線程的效率要比單線程高,其實不然。

BAT的一個對redis有很深瞭解的高級工程師曾經說過,redis就是如果所有數據都在內存裡,那麼單線程是效率最高的。為什麼這麼說呢,多線程的本質是CPU模擬出多個線程去操作,但是模擬是有代價的,學過操作系統的朋友應該知道,多線程之間切換是要切換上下文的,這也是對時間的一種消耗。所以,對於單處理器來說,當然是單線程,無切換才是最高效率的。redis就是用一塊CPU綁定了一塊內存,然後對數據的操作都是在這塊內存上進行的,基於此,單線程的redis已經達到了效率最大化。

我們用實際數據來說明。

一次CPU內存的切換大約需要1500ns,從內存中讀取1MB的數據,大概需要250us,就算我一次只讀1MB的數據,讀1000次之後,消耗在內存切換上這種非功能性過程上的消耗就達到了1500us,這個時間開銷任誰看都是不值。

此外,基於redis的單線程,我們還可以利用它提供的set key field value加nx參數的方式,來實現分佈式鎖。眾所周知,redis並不適合做數據持久層,更多的是取代memcache做緩存,做分佈式架構的支撐。分佈式架構勢必就要面臨如何實現分佈式鎖的問題,通過上面的接口,無論多少個分佈式節點,都可以準確的獲取分佈式鎖。

具體使用方式如下:通常來說,set函數是不管field字段是否存在,只要寫入成功就會返回1,但是如果增加了NX參數,那麼如果field值在redis中已經存在,就會返回空,否則才返回1。因此用這個函數來執行獲取分佈式鎖操作,如果返回值不為空,則加鎖成功,否則代表有其他線程在操作數據,當前請求需要等待。

此外,還有PX,XX參數,具體含義見如下文檔。


以上是我的淺見,歡迎各位在下方與我交流溝通。

我是蘇蘇思量,來自BAT的Java開發工程師,每天分享科技類見聞,歡迎各位關注我,與我共同進步。


一個存在感小透明


redis作為了一個內存緩存數據庫,設計成單線程,只是一個現階段工程技術上的一個比較合適的方案。

1.要設計成單線程,首要條件是網絡服務層要能在單線程模型上支撐大併發量,這一點LINUX通過EPOLL的網絡事件模型解決了。

2.單核CPU要足夠快,不能讓單個CPU成了redis的顯式瓶頸,當然還是有一些比較費CPU的操作,由於redis的單線程模型,而不適合在redis層解決,而是通過上層設計來規避。

3.緩存操作本身全是內存+CPU緩存來構建的,單個指令執行極快,單線程的緩存命中率也會有質的提升,因此收益也是比較大的。

4.壞處比如緩存持久化,是通過fork子進程來實現的,雖然LINUX對fork使用了各種優先,實際的fork操作對內存的使用量還是比較大的。

5.世界並不完美,我們只是找到了一箇中間方案,但向後看,CPU如果性能提升困難(目前現狀就是這樣,頻率提升極難),而業務總會越來越複雜,如果全在設計層解決是有代價的,不如在redis層解決方案。將來說不定就會出下一代的緩存數據庫方案,將又會是多線程了,同時支持緩存強計算。


TY丶唸經姐姐


為了保持數據的原子性。簡單說,同一個數據不能同時被多個線程所更改。所以,設計成單線程,保證了數據的安全。此外,神奇的是雖然是單線程,但是redis的處理的速度並不慢。


分享到:


相關文章: