背景:
python腳本監(jiān)控?cái)?shù)據(jù)進(jìn)行哈希分表,方案如下:
```
def gethashcode(str):
import hashlib
m = hashlib.md5()
m.update(str)
hashcode = m.hexdigest()
return int(hashcode, 16)
```
如上腳本哈希分表,key落入哪個(gè)分表,獲取的時(shí)候就從哪個(gè)分表取出。后臺(tái)PHP在實(shí)現(xiàn)匹配分表時(shí)要翻譯實(shí)現(xiàn)python的哈希分表方案唠倦。最初方案如下:
```
function gethashcode($k)
{
$hashcode = md5($k);//獲取32為16進(jìn)制字符串
return hexdec($hashcode);//將16進(jìn)制字符串轉(zhuǎn)為十進(jìn)制數(shù)字
}
```
如上PHP實(shí)現(xiàn)內(nèi)容會(huì)出現(xiàn)PHP大整型數(shù)據(jù)溢出問題,最后對(duì)table_nums進(jìn)行取模的時(shí)候會(huì)發(fā)生異常涮较。改良原理如下:
```
如果用一個(gè)int 型數(shù)據(jù)保存. 逐步解釋每一個(gè)字符乘以16^n的值再累加, 把字符串轉(zhuǎn)化成數(shù)字 再 mod 10的話稠鼻,會(huì)存在溢出的 問題, 所以這種思路不太好.
自己能想到最好的辦法是這樣的:讀出每一個(gè)字符對(duì)應(yīng)的于0~15的值(除最后一位)累加乘以6,再加上最后一位的值. 之后再 mod10 即是最終所求的余數(shù)..
原理:16^n = 10*k +6 (n,k為正整數(shù),且n>=1) 這個(gè)式中顯然成立.. 因此 (16^n)mod(10) = (10*k + 6)mod(10) = 6(n,k為正整數(shù),且n>=1).
因此除最后一位的數(shù).都可以直接簡(jiǎn)化為乘以6狂票,再加了最后一位的值. 最后mod 10即可.
示例: 比如 0x58fd7 mod 10 = ?
直接口算易知:(5 + 8 + 15 + 13)* 6 + 7 的結(jié)果mod10 為 3 候齿。。 有此方法上面的式中很長(zhǎng)都可以很快口算出來.何況用編程for循環(huán)呢..
```
以上原理參考文章:https://blog.csdn.net/w_sx12553/article/details/17526917
原理對(duì)應(yīng)方案:
```
function gethashcode($k)
{
$m16 = md5($k);
$m10 = 0;
for ($i=0; $i < strlen($m16); $i++) {
if($i == strlen($m16)-1) break;
$m10 += hexdec($m16[$i]);
}
$m10 = $m10*6+hexdec($m16[$i]);
return $m10;
}
$mod = $m10%table_nums;
```
over~