面試寶典系列-Hash碰撞是什麼?

哈希表(或散列表),是將鍵名key按指定的散列函數HASH通過HASH(key)計算後映射到表中一個記錄,而這個數組就是哈希表。這裏的HASH指任意的函數,例如MD五、CRC3二、SHA1或你自定義的函數實現。算法

理想狀況下HashTable的性能是O(1)的,性能消耗主要集中在散列函數HASH(key),經過HASH(key)直接定位到表中的記錄。
而在實際狀況下常常會發生key1 != key2,但HASH(key1) = HASH(key2),這種狀況即Hash碰撞問題,碰撞的機率越低HashTable的性能越好。固然Hash算法太過複雜也會影響HashTable性能(HashTable碰撞)json

PHP數組中,鍵名能夠爲數字或字符串類型。而在內核中只容許數字索引,對於字符串索引,內核採用了time33算法將字符串轉換爲整型(是對字符串的每一個字符轉換爲ASCII碼乘上33而且相加獲得的結果)數組

鍵名爲數字時:內核中哈希表的散列函數就是簡單的h & ht->nTableMask,其中h表明PHP中設置的索引號,nTableMask等於哈希表分配的長度-1。數據結構

鍵名爲字符串時:與數字索引相比,只是多了一步將字符串轉換爲整型。用到的算法是time33函數

HashTable碰撞:PHP中使用一個叫Backet的結構體表示桶,同一哈希值的全部桶被組織爲一個單鏈表。(先根據哈希值找到位置,而後再判斷原始key是否相同,若是不相同,找單鏈表下一個元素)post

PHP哈希表最小容量是8(2^3),最大容量是0×80000000(2^31),並向2的整數次冪圓整(即長度會自動擴展爲2的整數次冪,如13個元素的哈希表長度爲16;100個元素的哈希表長度爲128)性能

防hashTable碰撞攻擊(構造一個大數組,鍵值產生的哈希值都相同,而後post提交這個數組)在>=PHP5.3.9的版本中增長了一個配置項max_input_vars,用於標識一次http請求最大接收的參數個數,默認爲1000。但若是是json方式提交,並不能防止攻擊。索引

通常來講有兩種方式,一是限制每一個桶鏈表的最長長度;二是使用其它數據結構如紅黑樹取代鏈表組織碰撞哈希(並不解決哈希碰撞,只是減輕攻擊影響,將N個數據的操做時間從O(N^2)降至O(NlogN),代價是普通狀況下接近O(1)的操做均變爲O(logN))ip

相關文章
相關標籤/搜索