redis的哈希算法和java的HashMap有什么差別


這個問題是一個面試官問到的

 

到現在我也沒明白,他具體要問哪個?

 

有查了一些資料

 

本來大概也知道舊版的HashMap基本上就是傳統的數組+鏈表的方式實現,

 

1、對key進行hash算法,取模,比如取模20,那么數組的長度就是20

2、那么如果取模的話一定存在某些key在同一個數組索引中(也稱為同一個桶中),也可以叫hash沖突,這些概念都只是為了幫助理解,沒必要太糾結

那么如何解決hash沖突?就是上面說到的鏈表,桶中將會轉換成鏈表結構

我們可以理解為數組是一個一級索引,鏈表中才是真正的表數據

 

為什么不直接用全數組的形式:空間問題

缺陷:

1、哈希沖突頻繁情況下,性能問題:可能需要進行重新分配桶

2、鏈表數據量大的情況下,查詢性能的問題

 

Java8之后增加了紅黑樹的實現,紅黑樹是自平衡的二叉樹,能實現良好的查詢性能,相應的就是解決鏈表數據量大的情況下,查詢性能的問題(單桶數據量大)

 

 

那么我們再看看redis,redis中也是有hash的數據類型

 

由於redis使用的不是java語言,源碼並未過多分析,這邊參考下這個博客:https://blog.csdn.net/mccand1234/article/details/93411326

 

從這邊來看的,這里采用的應該和舊版的HashMap實現沒有太大差別。

 

所以我不太明白之前的面試官是挖坑給我,還是另有所指

 

 

所以在學習redis的同時,這邊又涉及到一個切片的問題,切片這邊指的是當系統承載的訪問量、數據量越來越多的情況下,單機甚至普通的集群業務分層都無法滿足的情況下,需要進行更細的切分

 

常用的三種切分方式:

  1、取模Hash

  2、隨機(適用於消息隊列模式,即不管你往哪一台機子存數據,都有消費者阻塞讀取,消費掉這個數據)

  3、一致性Hash

 

這邊也涉及到了hash算法,所以我也不太清楚是否面試官問的是這個

 

取模算法理論上和Java的HashMap應該也是差別不大

 

一致性Hash則有些不同

  1、構建一個0~2^32的一個環形空間(邏輯)

  2、通過對nodeName或者IP等進行hash函數取值,對應到這個環形空間的某個位置,代表具體的物理節點

  3、客戶端訪問的時候對數據也進行一樣的hash函數取值,對應到環形空間的某個位置,注意一般這里不會直接能找到物理節點,而是通過一個順時針或者逆時針的方式來獲取,這也是這個環形空間的存在意義(幫助理解)

  

存在的問題:

  1、新增節點:會對相近的節點造成影響,導致原來指向相近節點的客戶端,被重新指向新節點,造成緩存穿透;但是一般只影響一個節點,且如果只是作為緩存使用(而非數據庫),應該是可以容忍的

  2、數據傾斜的問題,數據分布可能會集中到某幾個節點中;這個和HashMap的桶中個別數據量特別大是一樣的道理。解決方式:可以通過一些虛擬節點,來讓環形中的節點更均勻


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM