57_分佈式緩存重建併發衝突問題以及zookeeper分佈式鎖解決方案


整個三級緩存的架構已經走通了nginx

咱們還遇到一個問題,就是說,若是緩存服務在本地的ehcache中都讀取不到數據,那就恩坑爹了redis

這個時候就意味着,須要從新到源頭的服務中去拉去數據,拉取到數據以後,趕忙先給nginx的請求返回,同時將數據寫入ehcache和redis中算法

分佈式重建緩存的併發衝突問題api

重建緩存:好比咱們這裏,數據在全部的緩存中都不存在了(LRU算法弄掉了),就須要從新查詢數據寫入緩存,重建緩存緩存

分佈式的重建緩存,在不一樣的機器上,不一樣的服務實例中,去作上面的事情,就會出現多個機器分佈式重建去讀取相同的數據,而後寫入緩存中架構

分佈式重建緩存的併發衝突問題。。。。。。併發

一、流量均勻分佈到全部緩存服務實例上分佈式

應用層nginx,是將請求流量均勻地打到各個緩存服務實例中的,可能我們的eshop-cache那個服務,可能會部署多實例在不一樣的機器上高併發

二、應用層nginx的hash,固定商品id,走固定的緩存服務實例oop

分發層的nginx的lua腳本,是怎麼寫的,怎麼玩兒的,搞一堆應用層nginx的地址列表,對每一個商品id作一個hash,而後對應用nginx數量取模

將每一個商品的請求固定分發到同一個應用層nginx上面去

在應用層nginx裏,發現本身本地lua shared dict緩存中沒有數據的時候,就採起同樣的方式,對product id取模,而後將請求固定分發到同一個緩存服務實例中去

這樣的話,就不會出現說多個緩存服務實例分佈式的去更新那個緩存了

留個做業,你們去作吧,這個東西,以前已經講解果了,lua腳本幾乎都是如出一轍的,咱們就不去作了,節省點時間

三、源信息服務發送的變動消息,須要按照商品id去分區,固定的商品變動走固定的kafka分區,也就是固定的一個緩存服務實例獲取到

緩存服務,是監聽kafka topic的,一個緩存服務實例,做爲一個kafka consumer,就消費topic中的一個partition

因此你有多個緩存服務實例的話,每一個緩存服務實例就消費一個kafka partition

因此這裏,通常來講,你的源頭信息服務,在發送消息到kafka topic的時候,都須要按照product id去分區

也就時說,同一個product id變動的消息必定是到同一個kafka partition中去的,也就是說同一個product id的變動消息,必定是同一個緩存服務實例消費到的

咱們也不去作了,其實很簡單,kafka producer api,裏面send message的時候,多加一個參數就能夠了,product id傳遞進去,就能夠了

四、問題是,本身寫的簡易的hash分發,與kafka的分區,可能並不一致!!!

咱們本身寫的簡易的hash分發策略,是按照crc32去取hash值,而後再取模的

關鍵你又不知道你的kafka producer的hash策略是什麼,極可能說跟咱們的策略是不同的

拿就可能致使說,數據變動的消息所到的緩存服務實例,跟咱們的應用層nginx分發到的那個緩存服務實例也許就不在一臺機器上了

這樣的話,在高併發,極端的狀況下,可能就會出現衝突

五、分佈式的緩存重建併發衝突問題發生了。。。

六、基於zookeeper分佈式鎖的解決方案

分佈式鎖,若是你有多個機器在訪問同一個共享資源,那麼這個時候,若是你須要加個鎖,讓多個分佈式的機器在訪問共享資源的時候串行起來

那麼這個時候,那個鎖,多個不一樣機器上的服務共享的鎖,就是分佈式鎖

分佈式鎖固然有不少種不一樣的實現方案,redis分佈式鎖,zookeeper分佈式鎖

zk,作分佈式協調這一塊,仍是很流行的,大數據應用裏面,hadoop,storm,都是基於zk去作分佈式協調

zk分佈式鎖的解決併發衝突的方案

(1)變動緩存重建以及空緩存請求重建,更新redis以前,都須要先獲取對應商品id的分佈式鎖(2)拿到分佈式鎖以後,須要根據時間版本去比較一下,若是本身的版本新於redis中的版本,那麼就更新,不然就不更新(3)若是拿不到分佈式鎖,那麼就等待,不斷輪詢等待,直到本身獲取到分佈式的鎖

相關文章
相關標籤/搜索