首頁 > 軟體

基於Python實現Hash演演算法

2022-03-18 19:00:10

1 前言

Simhash的演演算法簡單的來說就是,從海量文字中快速搜尋和已知simhash相差小於k位的simhash集合,這裡每個文字都可以用一個simhash值來代表,一個simhash有64bit,相似的文字,64bit也相似,論文中k的經驗值為3。該方法的缺點如優點一樣明顯,主要有兩點,對於短文字,k值很敏感;另一個是由於演演算法是以空間換時間,系統記憶體吃不消。

2 一般hash演演算法

最簡單的hash演演算法是用取餘的方式,根據hash地址存放資料,這需要提供鍵值對(Key-value)Key是地址,value是存放的資料

2.1 演演算法邏輯

  • 輸入存放資料,並建立(Key-value)物件
  • 通過取餘數的方式 公式:雜湊地址,d為資料,具有唯一性,n是樣本總數
  • 把產生的雜湊地址和對應資料儲存到字典物件中

2.2 程式碼實現

# 1.需要記錄的資料
records = [[1,50],[2,6],[3,47],[4,8],[5,9],[6,100]] # 資料鍵為日期,值為銷售數量
# 2.定義存放的地址和資料
Sadress1 = {'192.168.1.1':1}
Sadress2 = {'192.168.1.2':2}
Sadress3 = {'192.168.1.3':4}
Sadress4 = {'192.168.1.4':6}

# 資料長度定義為
n = 20

# 判斷雜湊值,分段為0-1-2-4-6
for one in records:
    if one[0] % n <= Sadress1['192.168.1.1']: 
        Sadress1[one[0]]=one[1]
    elif one[0] % n <= Sadress2['192.168.1.2']:
        Sadress2[one[0]] = one[1]
    elif one[0] % n <= Sadress3['192.168.1.3']:
        Sadress3[one[0]] = one[1]
    elif one[0] % n <= Sadress4['192.168.1.4']:
        Sadress4[one[0]] = one[1]

print(Sadress1)
print(Sadress2)
print(Sadress3)
print(Sadress4)

2.3 總結

  • 這是最簡單的Hash演演算法,還有MD5,SHAI,SHA2
  • 雜湊地址衝突,問題主要考慮輸入的唯一性取值方法
  • 在分散式計算中廣泛應用

3 一致性hash演演算法

一致性Hash演演算法時為了防止單個節點宕機或者刪除、新增,不會導致資料儲存的混亂或者無法儲存。一致性伺服器要求對伺服器地址通過雜湊演演算法也進行對映方式確定輸出地址,再加上對資料的雜湊處理,一直雜湊要實現兩個演演算法過程。

3.1 演演算法邏輯

  • 輸入資料,建立Key-value物件
  • 利用Hash演演算法產生雜湊地址,建立鍵值字典
  • 輸入伺服器地址,利用雜湊演演算法產生雜湊地址
  • 資料通過地址和伺服器地址,放到對應的範圍內
  • 輸出

3.2 程式碼實現

import hashlib # 匯入帶shal()雜湊演演算法的函數庫
class CHash(object):
    def __init__(self,nodes=None,v_num=2):# nodes節點存放節點地址,V-num一個節點對應,# 預設節點是為2
        self._v_num = v_num # 一個節點對應存放節點地址
        self._vNode_IP = {} # 用於虛擬節點的hash值與node的對應關係
        self._vNodeAdd = [] # 用於存放所有的虛擬節點的hash值,這裡需要保持排序
        for node in nodes:
            self.addNode(node)
        print('n虛擬節點雜湊值升序排列:n',self._vNodeAdd) # 對虛擬節點雜湊地址進行從小到大排序

    # 1 建立虛擬節點環,順序排列
    def addNode(self,node):
        for i in range(self._v_num):
            vNodeStr = '%s%s'%(node ,i) # 根據虛擬節點,為每個節點建立虛擬節點
            key = self._gen_key(vNodeStr) # 產生虛擬節點IP地址,伺服器節點IP+i
            print('虛擬節點字串',vNodeStr,'對應雜湊值',key)
            self._vNode_IP[key] = node # 虛擬節點雜湊地址為鍵,節點為IP地址為值
            self._vNodeAdd.append(key) # 對應虛擬節點雜湊地址進行獨立儲存
            self._vNodeAdd.sort()
    # 2 刪除退出節點地址及對應的虛擬地址
    def Del_Node(self,node): # 刪除退出節點地址及對應的虛擬地址
        for i in range(self._v_num):
            vNodeStr = '%s%s'%(node,i)
            key = self._gen_key(vNodeStr)  # 產生虛擬節點的雜湊地址
            del self._vNode_IP[key] # 通過雜湊地址刪除字典裡面的虛擬節點資訊
            self._vNodeAdd.remove(key) # 刪除虛擬節點的雜湊地址
    # 3 返回資料儲存對應的伺服器地址
    def dataNode(self,data):
        if self._vNodeAdd: # 虛擬節點的雜湊地址列表不為空
            key = self._gen_key(data) # 產生業務資料對應的雜湊地址
            print(data,'雜湊地址',key)
            for node_key in self._vNodeAdd: # 獲取虛擬節點的雜湊地址
                if key <= node_key: # 業務資料的雜湊地址<= 當前虛擬節點的雜湊地址
                    return self._vNode_IP[node_key] # 返回當前虛擬節點雜湊地址對應節點IP
            return self._vNodeAdd[self._vNodeAdd[0]] # 如果業務資料的雜湊值超過所有節點的地址,則歸入並返回第一個IP地址

        else:
            return None # 沒有節點

    # 4 通過shal()產生雜湊值
    @staticmethod # 裝飾器
    def _gen_key(key_str):
        Hash_value = hashlib.sha1(key_str.encode('utf-8')).hexdigest()

        return Hash_value

# 測試
C_H = CHash(['192.168.1.1','192.168.1.2','192.168.1.3','192.168.1.4'])
data =['Mike','Margge','Maria']
print('n正常情況下,儲存資料時,歸入的節點地址:')
print(data[0]+'存入的節點IP地址:',C_H.dataNode(data[0]))
print(data[1]+'存入的節點IP地址:',C_H.dataNode(data[1]))
print(data[2]+'存入的節點IP地址:',C_H.dataNode(data[2]))
# 192.168.2.1刪除節點
print('n192.168.1.2節點脫離分散式系統的情況:')
C_H.Del_Node('192.168.1.2') # 刪除節點
print(data[0]+'存入的節點IP地址:',C_H.dataNode(data[0]))
print(data[1]+'存入的節點IP地址:',C_H.dataNode(data[1]))
print(data[2]+'存入的節點IP地址:',C_H.dataNode(data[2]))

虛擬節點字串 192.168.1.10 對應雜湊值 f53e4ef74ec8f55440f9caf382c5f63c4a39b4bc
虛擬節點字串 192.168.1.11 對應雜湊值 239b32be446b1288655b570c23ccb51633c03927
虛擬節點字串 192.168.1.20 對應雜湊值 c385b891af246719e1a60c715be2f375aeab0b5b
虛擬節點字串 192.168.1.21 對應雜湊值 0d12ca599dc0316beec6436bb3beb04e84fbe3e2
虛擬節點字串 192.168.1.30 對應雜湊值 265180387f1642217973f8cfda2ca6cc92d48e60
虛擬節點字串 192.168.1.31 對應雜湊值 d6dacbe137bec9a047737207a3a82036f8454362
虛擬節點字串 192.168.1.40 對應雜湊值 7497a9439524d6f044fc22a8723039e0c42bbac8
虛擬節點字串 192.168.1.41 對應雜湊值 89c78508a642956363ed40326fce4346d7889f88

虛擬節點雜湊值升序排列:

 ['0d12ca599dc0316beec6436bb3beb04e84fbe3e2', '239b32be446b1288655b570c23ccb51633c03927', '265180387f1642217973f8cfda2ca6cc92d48e60', '7497a9439524d6f044fc22a8723039e0c42bbac8', '89c78508a642956363ed40326fce4346d7889f88', 'c385b891af246719e1a60c715be2f375aeab0b5b', 'd6dacbe137bec9a047737207a3a82036f8454362', 'f53e4ef74ec8f55440f9caf382c5f63c4a39b4bc']

正常情況下,儲存資料時,歸入的節點地址:

Mike 雜湊地址 d6ac022931a66a2bcc244db91818ebec76ce5e18
Mike存入的節點IP地址: 192.168.1.3
Margge 雜湊地址 ae5e1fda577bff360ed5da0b2804a1ff0b2a1675
Margge存入的節點IP地址: 192.168.1.2
Maria 雜湊地址 3e182b1ea9376483a38614d916a0b666ef531b6d
Maria存入的節點IP地址: 192.168.1.4

192.168.1.2節點脫離分散式系統的情況:

Mike 雜湊地址 d6ac022931a66a2bcc244db91818ebec76ce5e18
Mike存入的節點IP地址: 192.168.1.3
Margge 雜湊地址 ae5e1fda577bff360ed5da0b2804a1ff0b2a1675
Margge存入的節點IP地址: 192.168.1.3
Maria 雜湊地址 3e182b1ea9376483a38614d916a0b666ef531b6d
Maria存入的節點IP地址: 192.168.1.4

3.3 總結

  • 應用廣泛,很好的解決了伺服器宕機,節點刪除等問題
  • IP地址指向不同的伺服器存取地址,為不同的伺服器上的資料庫存取提供了便利

到此這篇關於基於Python實現Hash演演算法的文章就介紹到這了,更多相關Python實現Hash演演算法內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com