在後端中如何實現冪等和去重?

Java3y發表於2021-11-16

面試官要不你來講講你最近在看的點唄?可以拉出來一起討論下

候選者:最近在看「去重」和「冪等」相關的內容

面試官那你就先來聊聊你對「去重」和「冪等」的理解吧

候選者:我認為「冪等」和「去重」它們很像,我也說不出他們之間的嚴格區別

候選者:我說下我個人的理解,我也不知道對不對

候選者:「去重」是對請求或者訊息在「一定時間內」進行去重「N次」

候選者:「冪等」則是保證請求或訊息在「任意時間內」進行處理,都需要保證它的結果是一致的

候選者:不論是「去重」還是「冪等」,都需要對有一個「唯一 Key」,並且有地方對唯一Key進行「儲存」

候選者:以專案舉例,我維護的「訊息管理平臺」是有「去重」的功能的:「5分鐘相同內容訊息去重」「1小時內模板去重」「一天內渠道達到N次閾值去重」...

候選者:再次強調下「冪等」和「去重」的本質:「唯一Key」+「儲存」

面試官那你是怎麼做的呢

候選者:不同的業務場景,唯一Key是不一樣的,由業務決定

候選者:儲存選擇挺多的,比如「本地快取」/「Redis」/「MySQL」/「HBase」等等,具體選取什麼,也跟業務有關

候選者:比如說,在「訊息管理平臺」這個場景下,我儲存選擇的「Redis」(讀寫效能優越),Redis也有「過期時間」方便解決「一定時間內」的問題

候選者:而唯一Key,自然就是根據不同的業務構建不同的。

候選者:比如說「5分鐘相同內容訊息去重」,我直接MD5請求引數作為唯一Key。「1小時模板去重」則是「模板ID+userId」作為唯一Key,「一天內渠道去重」則是「渠道ID+userId」作為唯一Key...

面試官既然提到了「去重」了,你聽過布隆過濾器嗎?

候選者:自然是知道的啦

面試官來講講布隆過濾器吧,你為什麼不用呢?

候選者:布隆過濾器的底層資料結構可以理解為bitmap,bitmap也可以簡單理解為是一個陣列,元素只儲存0和1,所以它佔用的空間相對較小

候選者:當一個元素要存入bitmap時,其實是要去看儲存到bitmap的哪個位置,這時一般用的就是雜湊演算法,存進去的位置標記為1

候選者:標記為1的位置表示存在,標記為0的位置標示不存在

候選者:布隆過濾器是可以以較低的空間佔用來判斷元素是否存在進而用於去重,但是它也有對應的缺點

候選者:只要使用雜湊演算法離不開「雜湊衝突」,導致有存在「誤判」的情況

候選者:在布隆過濾器中,如果元素判定為存在,那該元素「未必」真實存在。如果元素判定為不存在,那就肯定是不存在

候選者:這應該不用我多解釋了吧?(結合「雜湊演算法」和「標記為1的位置表示存在,標記為0的位置標示不存在」這兩者就能得出上面結論)

候選者:布隆過濾器也不能「刪除」元素(也是雜湊演算法的侷限性,在布隆過濾器中是不能準確定位一個元素的)

候選者:如果要用的話,布隆過濾器的實現可以直接上Guava已經實現好的,不過這個是單機的

候選者:而分散式下的布隆過濾器,一般現在會用Redis,但也不是沒個公司都會部署布隆過濾器的Redis版(還是有侷限,像我以前公司就沒有)

候選者:所以,目前我負責的專案都是沒有用布隆過濾器的(:

候選者:如果「去重」開銷比較大,可以考慮建立「多層過濾」的邏輯

候選者:比如,先看看『本地快取』能不能過濾一部分,剩下「強校驗」交由『遠端儲存』(常見的Redis或者DB)進行二次過濾

面試官:嗯,那我就想起你上一次回答Kafka的時候了

面試官:當時你說在處理訂單時實現了at least one + 冪等

面試官:冪等處理時:前置過濾使用的是Redis,強一致校驗時使用的是DB唯一索引,也是為了提高效能,對吧?

面試官:唯一Key 好像就是 「訂單編號 + 訂單狀態」

候選者面試官你記性真的好!

候選者:一般我們需要對資料強一致性校驗,就直接上MySQL(DB),畢竟有事務的支援

候選者:「本地快取」如果業務適合,那可以作為一個「前置」判斷

候選者:Redis高效能讀寫,前置判斷和後置均可(:

候選者:而HBase則一般用於龐大資料量的場景下(Redis記憶體太貴,DB不夠靈活也不適合單表存大量資料)

候選者:至於冪等,一般的儲存還是「Redis」和「資料庫」

候選者:最最最最常見的就是資料庫「唯一索引」來實現冪等(我所負責的好幾個專案都是用這個)

候選者:構建「唯一Key」是業務相關的事了(:一般是用自己的業務ID進行拼接,生成一個"有意義"的唯一Key

候選者:當然,也有用「Redis」和「MySQL」實現分散式鎖來實現冪等的(:

候選者:但Redis分散式鎖是不能完全保證安全的,而MySQL實現分散式鎖(樂觀鎖和悲觀鎖還是看業務吧,我是沒用到過的)

候選者:網上有很多實現「冪等」的方案,本質上都是圍繞著「儲存」和「唯一Key」做了些變種,然後取了個名字...

候選者:總的來說,換湯不換藥(:

面試官:嗯...瞭解了

歡迎關注我的微信公眾號【Java3y】來聊聊Java面試,對線面試官系列持續更新中!

在後端中如何實現冪等和去重?

【對線面試官-移動端】系列 一週兩篇持續更新中!

【對線面試官-電腦端】系列 一週兩篇持續更新中!

原創不易!!求三連!!

相關文章