摘要:為了避免垃圾郵件給電子郵件的使用帶來不便,通過對電子郵件地址在垃圾電子郵件黑名單進行對比、過濾便成為一個行之有效的手段。項目從設(shè)計思想、具體實現(xiàn)以及性能提升等方面闡述了基于黑名單識別垃圾郵件地址技術(shù)。
關(guān)鍵詞:垃圾郵件;黑名單;數(shù)據(jù)庫;java BerkeleyDB
中圖分類號:TP311文獻標(biāo)識碼:A 文章編號:1009-3044(2009)36-10606-02
Design and Implementation of Anti-Spam module Based on the Blacklist of Email Address
LI Qiong
(Mianyang Normal University, Mianyang 621000, China)
Abstract: In order to avoid the inconvenience caused by Spam,filtering spam address in the blacklist has become an effective means. In this paper, the design, implementation, performance described blacklist technology to identify spam.
Key words: spam; blacklist; database; java BerkeleyDB
電子郵件是最常用的網(wǎng)絡(luò)應(yīng)用之一,已經(jīng)成為網(wǎng)絡(luò)交流溝通的重要途徑。但是,垃圾郵件(spam)隨著互聯(lián)網(wǎng)的不斷發(fā)展而大量增長,現(xiàn)在包含著商業(yè)宣傳、色情、政治,以及計算機病毒等不同內(nèi)容的垃圾郵件可以說是鋪天蓋地。我校為方便全校教師教學(xué)工作而自行開發(fā)的郵件服務(wù)器受到了垃圾郵件的侵害,給學(xué)校的教師的正常教學(xué)工作帶來極大的煩惱。為了解決這一問題,開發(fā)識別垃圾郵件模塊的需求迫在眉睫。
1 需求分析
設(shè)計一個合格的垃圾郵件地址過濾模塊,需要對模塊需求有個大致的分析:
1) 數(shù)據(jù)空間占用估算:目前我們已經(jīng)擁有一個近百萬級的垃圾郵件地址黑名單,為了滿足日后需要,我們設(shè)計一個擁有5百萬個垃圾電子郵件地址的黑名單,如果按照一個郵件地址約為28個字節(jié)的估算,則該黑名單約需占用133.51MB存儲空間大小(尚未包括附屬的空間開銷)。如果服務(wù)器不僅僅完成黑名單查詢工作,出于可靠以及內(nèi)存消耗考慮,所有垃圾郵件數(shù)據(jù)是需要通過使用磁盤來存儲。
2) 查詢時間占用估算:按照用戶收發(fā)郵件的習(xí)慣,大家希望能在數(shù)秒內(nèi)收到相應(yīng)的郵件,這就約束了郵件地址過濾時間應(yīng)該相當(dāng)短暫,不宜超過1~2秒。
3) 原來的郵件服務(wù)器是使用Java編寫的,為了能較好的與原郵件系統(tǒng)進行融合,過濾模塊同樣采用Java實現(xiàn)。
2 技術(shù)基礎(chǔ)
為了同時滿足以上必要條件,從而排除了使用java中Set、Map容器(雖然該容器有很高的查詢性能、但由于黑名單太大,這兩種容器無法處理這樣大量數(shù)據(jù))以及常見的關(guān)系/對象型數(shù)據(jù)庫(不能在很短的時間內(nèi)在5百萬的記錄中查詢出相應(yīng)結(jié)果),而號稱每秒能完成近百萬次查詢的高性能Berkeley DB是方案的不二之選。
Berkeley DB(BDB)是一個高性能的,嵌入數(shù)據(jù)庫編程庫,和C語言,C++,Java,Perl,Python,Tcl以及其他很多語言都有應(yīng)用程序編程界面。Berkeley DB可以保存任意類型的鍵/值對,而且可以為一個鍵保存多個數(shù)據(jù)。Berkeley DB可以支持?jǐn)?shù)千的并發(fā)線程同時操作數(shù)據(jù)庫,支持最大256TB的數(shù)據(jù),廣泛用于各種操作系統(tǒng)包括大多數(shù)Unix類操作系統(tǒng)和Windows操作系統(tǒng)以及實時操作系統(tǒng)。數(shù)據(jù)訪問算法可選用B+樹算法、HASH算法、Recno算法和Queue算法。
經(jīng)過實際測試,Berkeley DB確實能勝任該項任務(wù)。
3 設(shè)計及實現(xiàn)
Berkeley DB作為垃圾郵件地址黑名單的存儲、查詢引擎,整個模塊設(shè)計及實現(xiàn)盡可能圍繞著提高處理性能展開。垃圾郵件地址作為Key(Data在這里沒有存在的意義,但由于數(shù)據(jù)庫的需要,就用1個字節(jié)的任意數(shù)值代替),記入黑名單數(shù)據(jù)庫中。為了減小存儲空間并提高性能,模塊里對垃圾郵件地址作了一次反轉(zhuǎn)操作,如將15608111788@sc.com轉(zhuǎn)換為“moc.cs@88711180651”,使得整個黑名單數(shù)據(jù)的字母順序非常接近,大大提高了緩存的效率和性能。對于海量數(shù)據(jù)Berkeley DB支持B+Tree以及Hash兩種訪問算法,通過分析垃圾郵件地址的規(guī)律,并且通過實際測試(采用了9百萬的數(shù)據(jù)),最終選擇了B+ Tree算法。Berkeley DB本身還提供三種操作方式:Transactional(事物)、 Concurrent(并發(fā))和Private(私有)。出于目前作為單機系統(tǒng)的考慮,模塊采用Private方式,極大提高訪問速度。
整個模塊以blacklist類來定義并實現(xiàn),其他代碼直接調(diào)用該類的類成員方法即可實現(xiàn)相應(yīng)功能,以下是blacklist類的定義:
public class blacklist
{
private Environment m_DbEnvironment = 1;
privateDatabase m_Db = 1;
private static final String m_DbFileName = \"blacklist.db\"; //黑名單庫的名稱
private static final File m_EnvDir = new File(\"/blacklist/env\"); //BDB的環(huán)境文件目錄
private static final File m_DbDir = new File(\"/blacklist/db\");//BDB的數(shù)據(jù)庫文件目錄
public blacklist() {…}
public boolean blacklist_open(){…} //打開數(shù)據(jù)庫
public void blacklist_close(){…} //關(guān)閉數(shù)據(jù)庫
public void blacklist_append(String email){…} //在數(shù)據(jù)庫中追加黑名單
public boolean blacklist_delete(String email){…} //在數(shù)據(jù)庫中刪除黑名單
public long blacklist_load(String filename){…} //從文件中批量導(dǎo)入黑名單
public boolean blacklist_search(String email){…} //在數(shù)據(jù)庫中查找是否垃圾郵件
}
從以上類的定義中可看出類方法主要由load(從垃圾郵件名單文本文件中批量載入并保存至黑名單數(shù)據(jù)庫中)、search(對任意郵件地址在黑名單數(shù)據(jù)中查詢)、append(添加單個垃圾郵件地址至黑名單數(shù)據(jù)庫中)和delete(從黑名單數(shù)據(jù)庫中刪除單個垃圾郵件地址)四個主要功能方法以及open和close兩個輔助方法構(gòu)成。
下面的例子使用blacklist類的load方法對含有915萬個郵件地址進行導(dǎo)入測試:
(測試計算機配置:CPU為Intel P4 3.00GHz、RAM 512M、硬盤 IDE 7200RPM、WinXP SP2、JDK 1.6、Berkeley DB 4.7.25)
public class load {
public load() { }
public static void main(String[] args) {
blacklist app = new blacklist();
app.open();
long start, end;
start = System.currentTimeMillis();
app.load(\"/blacklist/915.txt\");
end = System.currentTimeMillis();
System.out.println(\"load file(ms):\" + (end - start));
app.close();
}
}
結(jié)果為:load file(ms):1312516
生成一個文件大小為413M的垃圾郵件地址的黑名單數(shù)據(jù)庫,耗時也不過1313秒。通過以上結(jié)果可計算出,模塊進行批量導(dǎo)入時每秒可導(dǎo)入5243個郵件地址。
下面這個簡單例子,在相同平臺下對先前生成的黑名單進行模擬查詢測試(測試的樣本為2000個郵件地址,其中1000個在黑名單中,剩余1000個不在黑名單中):
public class query
{
public query() {}
public static void main(String[] args)
{
blacklist app = new blacklist();
app.open();
long start = 0, end = 0;
File file = new File(\"/blacklist/test.txt\");
BufferedReader reader = 1;
start = System.currentTimeMillis();
try
{reader = new BufferedReader(new FileReader(file));
String line = 1;
while ((line = reader.readLine()) != 1)
{app.search(line);
}
reader.close();
}
catch (IOException e)
{
e.printStackTrace();
}
end = System.currentTimeMillis();
System.out.println((end-start) + \"ms\");
app.close();
}
}
結(jié)果為:156ms(毫秒)
可見,不論是否在黑名單庫中,判別一個郵件地址的速度極快,每秒種可完成約12820次查詢)。
整個模擬測試運行中包括java虛擬機本身整個空間占用約為13M(包含1M緩存),基本滿足垃圾郵件地址過濾的功能需求。
4 性能提高
如果需要增強垃圾郵件地址過濾處理能力,現(xiàn)有單機系統(tǒng)可以采用號稱讀取100萬數(shù)據(jù)只需要0.33秒的Tokyo Cabinet數(shù)據(jù)庫,該數(shù)據(jù)庫比Berkeley DB 快3倍左右,并且能過Tokyo Tyrant輕松實現(xiàn)分布式處理。只是由于只能運行于Linux及32位操作系統(tǒng)下存在單個數(shù)據(jù)庫文件不能超過2G的限制,因而本次沒有采用該數(shù)據(jù)庫引擎。
另外還可以采用分布式計算,更可大幅度提高整個模塊處理性能,例如采用FastDHT(高性能分布式Hash系統(tǒng),底層存儲仍采用Berkeley DB)、BigTable、HBase以及上面提到的Tokyo Tyrant等等,只是識別正確率可能會隨著分布式系統(tǒng)的可能出現(xiàn)的節(jié)點故障而有所下降。
5 結(jié)束語
本文研究了對大批量垃圾郵件地址黑名單的存儲、查詢處理,在保證了較高的正確率、較少的空間占用的前提下,能夠以較快的速度完成查詢過濾工作,并且接口方法簡單,較好的達到模塊要求。
該模塊經(jīng)過近2個月的運行,工作正常,有效地阻止了垃圾郵件的傳播,極大地改善了教學(xué)環(huán)境,較好的達到防止垃圾郵件的目的。
參考文獻:
[1] 《嵌入式數(shù)據(jù)庫系統(tǒng)Berkeley DB》.http://www.ibm.com/developerworks/cn/linux/l-embdb/index.html.
[2] 《Getting Started with Berkeley DB for Java》. http://www.oracle.com/technology/documentation/berkeley-db/db/gsg/JAVA/BerkeleyDB-Core-JAVA-GSG.pdf.
[3] Bind DLZ. http://bind-dlz.sourceforge.net/bdbhpt_driver.html.