大白話聊聊Java併發面試問題之微服務註冊中心的讀寫鎖優化【石杉的架構筆記】

歡迎關注我的公衆號:石杉的架構筆記(ID:shishan100)
java

週一至週五早8點半!精品技術文章準時送上!面試


1、讀寫鎖的介紹

上一篇文章大白話聊聊Java併發面試問題之公平鎖與非公平鎖是啥?,聊了一下java併發包的公平鎖和非公平鎖。算法

這篇文章來聊一下讀寫鎖。所謂的讀寫鎖,就是將一個鎖拆分爲讀鎖和寫鎖兩個鎖,而後你加鎖的時候,能夠加寫鎖,也能夠加讀鎖。以下面代碼所示:緩存

若是有一個線程加了寫鎖,那麼其餘線程就不能加寫鎖了,同一時間只能容許一個線程加寫鎖。由於加了寫鎖就意味着有人要寫一個共享數據,那同時就不能讓其餘人來寫這個數據了。安全

同時若是有線程加了寫鎖,其餘線程就不能加讀鎖了,由於既然都有人在寫數據了,你其餘人固然不能來讀數據了!性能優化

若是有一個線程加了讀鎖,別的線程是能夠隨意同時加讀鎖的,由於只是有線程在讀數據而已,此時別的線程也是能夠來讀數據的!多線程

同理,若是一個線程加了讀鎖,此時其餘線程是不能夠加寫鎖的,由於既然有人在讀數據,那就不能讓你隨意來寫數據了!架構

好了!這個就是初步介紹一下讀寫鎖的使用方法,相信不少同窗應該以前都知道了,由於這個是java開發中很是基礎的一塊知識。併發


2、微服務註冊中心的讀寫鎖優化

如今進入主題,咱們主要聊一下微服務註冊中內心面的讀寫鎖優化。分佈式

爲何要聊一下這個問題呢?

由於若是你出去面試,極可能被問到讀寫鎖的問題,此時你能夠天然而然的帶出來,你以前瞭解過Spring Cloud微服務技術架構,同時對裏面的微服務註冊中心的註冊表讀寫鎖優化有一些本身的感悟和見解。

這樣的話,相比於你簡單的給面試官聊聊讀寫鎖的基本概念和使用方法,要增色很多!

首先,你們須要瞭解一點微服務的總體架構知識,能夠參考以前寫過的一篇文章:拜託!面試請不要再問我Spring Cloud底層原理!

同時還須要瞭解一下Spring Cloud Eureka(即微服務註冊中心)的核心原理。這個能夠參考以前寫過的一篇文章微服務註冊中心如何承載大型系統的千萬級訪問?的。

好,瞭解了這些前置知識以後,咱們正式開始。

先來看看下面的圖,如今咱們知道一個微服務註冊中心(能夠是Eureka或者Consul或者你本身寫的一個微服務註冊中心),他確定會在內存中有一個服務註冊表的概念。

這個服務註冊表中就是存放了各個微服務註冊時發送過來的本身的地址信息,裏面保存了每一個服務有多少個服務實例,每一個服務實例部署在哪臺機器上監聽哪一個端口號,主要是這樣的一些信息。

OK,那如今問題來了,這個服務註冊表的數據,實際上是有人讀也有人寫的。

舉個例子,好比有的服務啓動的時候會來註冊,此時就會修改服務註冊表的數據,這個就是寫的過程。

接着,別的服務也會來讀這個服務註冊表的數據,由於每一個服務都須要感知到其餘服務在哪些機器上部署。

因此,這個內存裏的服務註冊表數據,自然就是有讀寫併發問題的!可能會有多個線程來寫,也可能會有多個線程來讀!

若是你對同一分內存中的註冊表數據不加任何保護措施,那麼可能會有多線程併發修改共享數據的問題,可能致使數據錯亂,對吧?

上述過程,你們看看下面的圖,就明白了。

此時,若是對服務註冊表的服務註冊和讀取服務註冊表的方法,都加一個synchronized關鍵字,是否是就能夠了呢?

或許你會想,加上synchronized,直接讓全部線程對服務註冊表的讀寫操做,所有串行化。那不就能夠保證內存中的服務註冊表數據安全了嗎?

下面是一段僞代碼,你們來感覺一下:

在上面的代碼中直接給寫(服務註冊)讀(讀取服務註冊表)兩個方法,都暴力的加上了synchronized關鍵字,確實是能夠保證服務註冊表的數據不錯亂,可是這樣確定是不太合適的。

由於這麼搞的話,至關因而全部的線程讀寫服務註冊表數據,所有串行化了。

你們思考一下,咱們想要的效果是什麼?其實不就是在有人往服務註冊表裏寫數據的時候,就不讓其餘人寫了,同時也不讓其餘人讀!

而後,有人在讀服務註冊表的數據的時候,其餘人均可以隨便同時讀,可是此時不容許別人寫服務註冊表數據了!

對吧,咱們想要的,其實不就是這個效果嗎?

想清楚了這點,咱們就不該該暴力的加一個synchronized,讓全部讀寫線程所有串行化,那樣會致使併發性很是的低。

你們看看下面的圖,咱們想要的第一個效果:一旦有人在寫服務註冊表數據,咱們加個寫鎖,此時別人不能寫,也不能讀。

那麼若是有人在讀數據呢?此時就可讓別人均可以讀,可是不容許任何人寫。你們看下面的圖。

關鍵點來了,這樣作有什麼好處呢?其實大部分時候都是讀操做,因此使用讀鎖可讓大量的線程同時來讀數據,不須要阻塞不須要排隊,保證高併發讀的性能是比較高的。

而後少許的時候是有服務上線要註冊數據,寫數據的場景是比較少的,此時寫數據的時候,只能一個一個的加寫鎖而後寫數據,同時寫數據的時候就不容許別人來讀數據了。

因此讀寫鎖是很是適合這種讀多寫少的場景的。

另外,咱們能不能儘可能在寫數據的期間還保證能夠繼續讀數據呢?大量加讀鎖的時候,會阻塞人家寫數據加寫鎖過長時間,這種狀況可否避免呢?

能夠的,採用多級緩存的機制,具體能夠參加以前的一篇文章:微服務註冊中心如何承載大型系統的千萬級訪問?、。裏面分析了Spring Cloud Eureka微服務註冊中內心的多級緩存機制。

最後看下上面那段僞代碼若是用讀寫鎖來優化是怎麼樣的?


END


若有收穫,請幫忙轉發,您的鼓勵是做者最大的動力,謝謝!


一大波微服務、分佈式、高併發、高可用的原創系列文章正在路上

歡迎掃描下方二維碼,持續關注:


石杉的架構筆記(id:shishan100)

十餘年BAT架構經驗傾囊相授


推薦閱讀:

一、拜託!面試請不要再問我Spring Cloud底層原理

二、【雙11狂歡的背後】微服務註冊中心如何承載大型系統的千萬級訪問?

三、【性能優化之道】每秒上萬併發下的Spring Cloud參數優化實戰

四、微服務架構如何保障雙11狂歡下的99.99%高可用

五、兄弟,用大白話告訴你小白都能聽懂的Hadoop架構原理

六、大規模集羣下Hadoop NameNode如何承載每秒上千次的高併發訪問

七、【性能優化的祕密】Hadoop如何將TB級大文件的上傳性能優化上百倍

八、拜託,面試請不要再問我TCC分佈式事務的實現原理坑爹呀!

九、【坑爹呀!】最終一致性分佈式事務如何保障實際生產中99.99%高可用?

十、拜託,面試請不要再問我Redis分佈式鎖的實現原理!

十一、【眼前一亮!】看Hadoop底層算法如何優雅的將大規模集羣性能提高10倍以上?

十二、億級流量系統架構之如何支撐百億級數據的存儲與計算

1三、億級流量系統架構之如何設計高容錯分佈式計算系統

1四、億級流量系統架構之如何設計承載百億流量的高性能架構

1五、億級流量系統架構之如何設計每秒十萬查詢的高併發架構

1六、億級流量系統架構之如何設計全鏈路99.99%高可用架構

1七、七張圖完全講清楚ZooKeeper分佈式鎖的實現原理

1八、大白話聊聊Java併發面試問題之volatile究竟是什麼?

1九、大白話聊聊Java併發面試問題之Java 8如何優化CAS性能?

20、大白話聊聊Java併發面試問題之談談你對AQS的理解?

2一、大白話聊聊Java併發面試問題之公平鎖與非公平鎖是啥?

相關文章
相關標籤/搜索