這篇文章帶給大家的內容是關於如何使用Redis的Bloomfilter去重,既用上了Bloomfilter的海量去重能力,又用上了Redis的可持久化能力,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。
前言:
「去重」是日常工作中會常用到的技能,在爬蟲領域更是常用,而且規模一般都比較大。去重需要考慮兩個點:去重的資料量、去重速度。為了保持較快的去重速度,一般選擇在記憶體中去重。
資料量不大時,可以直接放在記憶體裡面去重,例如python可以使用set()去重。
當去重資料需要持久化時可以使用redis的set資料結構。
當資料量再大一點時,可以用不同的加密演算法先將長字串壓縮成16/32/40 個字符,再使用上面兩種方法去重;
當資料量達到億(甚至十億、百億)數量級時,記憶體有限,必須用「位」來去重,才能滿足需求。 Bloomfilter就是將去重物件對應到幾個記憶體“位元”,透過幾個位元的 0/1值來判斷一個物件是否已經存在。
然而Bloomfilter運作在一台機器的記憶體上,不方便持久化(機器down掉就什麼都沒啦),也不方便分散式爬蟲的統一去重。如果可以在Redis申請記憶體進行Bloomfilter,以上兩個問題就都能解決了。
程式碼:
# encoding=utf-8import redisfrom hashlib import md5class SimpleHash(object): def __init__(self, cap, seed): self.cap = cap self.seed = seed def hash(self, value): ret = 0 for i in range(len(value)): ret += self.seed * ret + ord(value[i]) return (self.cap - 1) & retclass BloomFilter(object): def __init__(self, host='localhost', port=6379, db=0, blockNum=1, key='bloomfilter'): """ :param host: the host of Redis :param port: the port of Redis :param db: witch db in Redis :param blockNum: one blockNum for about 90,000,000; if you have more strings for filtering, increase it. :param key: the key's name in Redis """ self.server = redis.Redis(host=host, port=port, db=db) self.bit_size = 1 << 31 # Redis的String类型最大容量为512M,现使用256M self.seeds = [5, 7, 11, 13, 31, 37, 61] self.key = key self.blockNum = blockNum self.hashfunc = [] for seed in self.seeds: self.hashfunc.append(SimpleHash(self.bit_size, seed)) def isContains(self, str_input): if not str_input: return False m5 = md5() m5.update(str_input) str_input = m5.hexdigest() ret = True name = self.key + str(int(str_input[0:2], 16) % self.blockNum) for f in self.hashfunc: loc = f.hash(str_input) ret = ret & self.server.getbit(name, loc) return ret def insert(self, str_input): m5 = md5() m5.update(str_input) str_input = m5.hexdigest() name = self.key + str(int(str_input[0:2], 16) % self.blockNum) for f in self.hashfunc: loc = f.hash(str_input) self.server.setbit(name, loc, 1)if __name__ == '__main__':""" 第一次运行时会显示 not exists!,之后再运行会显示 exists! """ bf = BloomFilter() if bf.isContains('http://www.baidu.com'): # 判断字符串是否存在 print 'exists!' else: print 'not exists!' bf.insert('http://www.baidu.com')
#說明:
Bloomfilter演算法如何使用位去重,這個百度上有很多解釋。簡單點說就是有幾個seeds,現在申請一段內存空間,一個seed可以和字符串哈希映射到這段內存上的一個位,幾個位都為1即表示該字符串已經存在。插入的時候也是,將映射出的幾個位元都置為1。
要提醒的是Bloomfilter演算法會有漏失機率,即不存在的字串有一定機率被誤判為已經存在。這個機率的大小與seeds的數量、申請的記憶體大小、去重物件的數量有關。下面有一張表,m表示記憶體大小(多少個位元),n表示去重物件的數量,k表示seed的個數。例如我代碼中申請了256M,也就是1
基於Redis的Bloomfilter去重,其實就是利用了Redis的String資料結構,但Redis一個String最大隻能512M,所以如果去重的數據量大,需要申請多個去重塊(程式碼中blockNum即表示去重塊的數量)。
程式碼中使用了MD5加密壓縮,將字串壓縮到了32個字元(也可用hashlib.sha1()壓縮成40個字元)。它有兩個作用,一是Bloomfilter對一個很長的字串雜湊映射的時候會出錯,經常誤判為已存在,壓縮後就不再有這個問題;二是壓縮後的字元為0~f共16中可能,我截取了前兩個字符,再根據blockNum將字符串指定到不同的去重塊進行去重。
總結:
基於Redis的Bloomfilter去重,既用上了Bloomfilter的海量去重能力,又用上了Redis的可持久化能力,基於Redis也方便分散式機器的去重。在使用的過程中,要預算好待去重的資料量,則根據上面的表,適當地調整seed的數量和blockNum數量(seed越少肯定去重速度越快,但漏失率越大)。
以上是在爬蟲的過程中如何使用Redis的Bloomfilter去重的詳細內容。更多資訊請關注PHP中文網其他相關文章!

使用數據庫存儲會話的主要優勢包括持久性、可擴展性和安全性。 1.持久性:即使服務器重啟,會話數據也能保持不變。 2.可擴展性:適用於分佈式系統,確保會話數據在多服務器間同步。 3.安全性:數據庫提供加密存儲,保護敏感信息。

在PHP中實現自定義會話處理可以通過實現SessionHandlerInterface接口來完成。具體步驟包括:1)創建實現SessionHandlerInterface的類,如CustomSessionHandler;2)重寫接口中的方法(如open,close,read,write,destroy,gc)來定義會話數據的生命週期和存儲方式;3)在PHP腳本中註冊自定義會話處理器並啟動會話。這樣可以將數據存儲在MySQL、Redis等介質中,提升性能、安全性和可擴展性。

SessionID是網絡應用程序中用來跟踪用戶會話狀態的機制。 1.它是一個隨機生成的字符串,用於在用戶與服務器之間的多次交互中保持用戶的身份信息。 2.服務器生成並通過cookie或URL參數發送給客戶端,幫助在用戶的多次請求中識別和關聯這些請求。 3.生成通常使用隨機算法保證唯一性和不可預測性。 4.在實際開發中,可以使用內存數據庫如Redis來存儲session數據,提升性能和安全性。

在無狀態環境如API中管理會話可以通過使用JWT或cookies來實現。 1.JWT適合無狀態和可擴展性,但大數據時體積大。 2.Cookies更傳統且易實現,但需謹慎配置以確保安全性。

要保護應用免受與會話相關的XSS攻擊,需採取以下措施:1.設置HttpOnly和Secure標誌保護會話cookie。 2.對所有用戶輸入進行輸出編碼。 3.實施內容安全策略(CSP)限制腳本來源。通過這些策略,可以有效防護會話相關的XSS攻擊,確保用戶數據安全。

优化PHP会话性能的方法包括:1.延迟会话启动,2.使用数据库存储会话,3.压缩会话数据,4.管理会话生命周期,5.实现会话共享。这些策略能显著提升应用在高并发环境下的效率。

theSession.gc_maxlifetimesettinginphpdeterminesthelifespanofsessiondata,setInSeconds.1)它'sconfiguredinphp.iniorviaini_set().2)abalanceisesneededeededeedeedeededto toavoidperformance andunununununexpectedLogOgouts.3)

在PHP中,可以使用session_name()函數配置會話名稱。具體步驟如下:1.使用session_name()函數設置會話名稱,例如session_name("my_session")。 2.在設置會話名稱後,調用session_start()啟動會話。配置會話名稱可以避免多應用間的會話數據衝突,並增強安全性,但需注意會話名稱的唯一性、安全性、長度和設置時機。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Atom編輯器mac版下載
最受歡迎的的開源編輯器

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)