本文闡述的是一款經(jīng)過生產(chǎn)環(huán)境檢驗(yàn)的千萬級數(shù)據(jù)全文檢索(搜索引擎)架構(gòu)。本文只列出前幾章的內(nèi)容節(jié)選,不提供全文內(nèi)容。
在DELL PowerEdge 6850服務(wù)器(四顆64 位Inter Xeon MP 7110N處理器 / 8GB內(nèi)存)、RedHat AS4 Linux操作系統(tǒng)、MySQL 5.1.26、MyISAM存儲引擎、key_buffer=1024M環(huán)境下實(shí)測,單表1000萬條記錄的數(shù)據(jù)量(這張MySQL表擁有int、datetime、varchar、text等類型的10多個(gè)字段,只有主鍵,無其它索引),用主鍵(PRIMARY KEY)作為WHERE條件進(jìn)行SQL查詢,速度非常之快,只耗費(fèi)0.01秒。
出自俄羅斯的開源全文搜索引擎軟件 Sphinx ,單一索引最大可包含1億條記錄,在1千萬條記錄情況下的查詢速度為0.x秒(毫秒級)。Sphinx創(chuàng)建索引的速度為:創(chuàng)建100萬條記錄的索引只需3~4分鐘,創(chuàng)建1000萬條記錄的索引可以在50分鐘內(nèi)完成,而只包含最新10萬條記錄的增量索引,重建一次只需幾十秒。
基于以上幾點(diǎn),我設(shè)計(jì)出了這套搜索引擎架構(gòu)。在生產(chǎn)環(huán)境運(yùn)行了一周,效果非常不錯(cuò)。有時(shí)間我會專為配合Sphinx搜索引擎,開發(fā)一個(gè)邏輯簡單、速度快、占用內(nèi)存低、非表鎖的MySQL存儲引擎插件,用來代替MyISAM引擎,以解決MyISAM存儲引擎在頻繁更新操作時(shí)的鎖表延遲問題。另外,分布式搜索技術(shù)上已無任何問題。
一、搜索引擎架構(gòu)設(shè)計(jì):
1、搜索引擎架構(gòu)圖:

2、搜索引擎架構(gòu)設(shè)計(jì)思路:
(1)、調(diào)用方式最簡化:
盡量方便前端Web工程師,只需要一條簡單的SQL語句“SELECT ... FROM myisam_table JOIN sphinx_table ON (sphinx_table.sphinx_id=myisam_table.id) WHERE query='...';”即可實(shí)現(xiàn)高效搜索。
(2)、創(chuàng)建索引、查詢速度快:
①、Sphinx Search 是由俄羅斯人Andrew Aksyonoff 開發(fā)的高性能全文搜索軟件包,在GPL與商業(yè)協(xié)議雙許可協(xié)議下發(fā)行。
Sphinx的特征:
- Sphinx支持高速建立索引(可達(dá)10MB/秒,而Lucene建立索引的速度是1.8MB/秒)
- 高性能搜索(在2-4 GB的文本上搜索,平均0.1秒內(nèi)獲得結(jié)果)
- 高擴(kuò)展性(實(shí)測最高可對100GB的文本建立索引,單一索引可包含1億條記錄)
- 支持分布式檢索
- 支持基于短語和基于統(tǒng)計(jì)的復(fù)合結(jié)果排序機(jī)制
- 支持任意數(shù)量的文件字段(數(shù)值屬性或全文檢索屬性)
- 支持不同的搜索模式(“完全匹配”,“短語匹配”和“任一匹配”)
- 支持作為Mysql的存儲引擎
②、通過國外《High Performance MySQL》專家組的測試可以看出,根據(jù)主鍵進(jìn)行查詢的類似“SELECT ... FROM ... WHERE id = ...”的SQL語句(其中id為PRIMARY KEY),每秒鐘能夠處理10000次以上的查詢,而普通的SELECT查詢每秒只能處理幾十次到幾百次:

③、Sphinx不負(fù)責(zé)文本字段的存儲。假設(shè)將數(shù)據(jù)庫的id、date、title、body字段,用sphinx建立搜索索引。根據(jù)關(guān)鍵字、時(shí)間、類別、范圍等信息查詢一下sphinx,sphinx只會將查詢結(jié)果的ID號等非文本信息告訴我們。要顯示title、body等信息,還需要根據(jù)此ID號去查詢MySQL數(shù)據(jù)庫,或者從Memcachedb等其他的存儲中取得。安裝SphinxSE作為MySQL的存儲引擎,將MySQL與Sphinx結(jié)合起來,是一種便捷的方法。
創(chuàng)建一張Sphinx類型表,將MyISAM表的主鍵ID和Sphinx表的ID作一個(gè)JOIN聯(lián)合查詢。這樣,對于MyISAM表來所,只相當(dāng)于一個(gè)WHERE id=...的主鍵查詢,WHERE后的條件都交給Sphinx去處理,可以充分發(fā)揮兩者的優(yōu)勢,實(shí)現(xiàn)高速搜索查詢。
(3)、按服務(wù)類型進(jìn)行分離:
為了保證數(shù)據(jù)的一致性,我在配置Sphinx讀取索引源的MySQL數(shù)據(jù)庫時(shí),進(jìn)行了鎖表。Sphinx讀取索引源的過程會耗費(fèi)一定時(shí)間,由于MyISAM存儲引擎的讀鎖和寫鎖是互斥的,為了避免寫操作被長時(shí)間阻塞,導(dǎo)致數(shù)據(jù)庫同步落后跟不上,我將提供“搜索查詢服務(wù)”的和提供“索引源服務(wù)”的MySQL數(shù)據(jù)庫進(jìn)行了分開。監(jiān)聽3306端口的MySQL提供“搜索查詢服務(wù)”,監(jiān)聽3406端口的MySQL提供“索引源服務(wù)”。
(4)、“主索引+增量索引”更新方式:
一般網(wǎng)站的特征:信息發(fā)布較為頻繁;剛發(fā)布完的信息被編輯、修改的可能性大;兩天以前的老帖變動性較小。
基于這個(gè)特征,我設(shè)計(jì)了Sphinx主索引和增量索引。對于前天17:00之前的記錄建立主索引,每天凌晨自動重建一次主索引;對于前天17:00之后到當(dāng)前最新的記錄,間隔3分鐘自動重建一次增量索引。
(5)、“Ext3文件系統(tǒng)+tmpfs內(nèi)存文件系統(tǒng)”相結(jié)合:
為了避免每3分鐘重建增量索引導(dǎo)致磁盤IO較重,從而引起系統(tǒng)負(fù)載上升,我將主索引文件創(chuàng)建在磁盤,增量索引文件創(chuàng)建在tmpfs內(nèi)存文件系統(tǒng)“/dev/shm/”內(nèi)?!?dev/shm/”內(nèi)的文件全部駐留在內(nèi)存中,讀寫速度非???。但是,重啟服務(wù)器會導(dǎo)致“/dev/shm/”內(nèi)的文件丟失,針對這個(gè)問題,我會在服務(wù)器開機(jī)時(shí)自動創(chuàng)建“/dev/shm/”內(nèi)目錄結(jié)構(gòu)和Sphinx增量索引。
(6)、中文分詞詞庫:
我根據(jù)“百度早期中文分詞庫”+“搜狗拼音輸入法細(xì)胞詞庫”+“LibMMSeg高頻字庫”+... 綜合整理成一份中文分詞詞庫,出于某些考慮暫不提供。你可以使用LibMMSeg自帶的中文分詞詞庫。