什麼是關鍵字鏈結?
什麼是關鍵字鏈結?
部落格服務
hatena diary
()支援關鍵字鏈結,這是個很特別的功能。
該功能在前面的圖5.3
(p.112
)的關鍵字鏈結截圖中已介紹過。如圖5.3
所示,寫部落格時部分關鍵字會自動加上鏈結,鏈結目標就是該關鍵字的解釋頁面。
wiki
的實現也能給
wiki
關鍵字自動加鏈結,這個功能與它很相似。
被鏈結的關鍵字就是使用者在
)上新增的關鍵字。本書執筆時(
2023年8
月),hatena keyword
已有27
萬條以上關鍵字,使用者每天建立的新關鍵字大約有
100個。
關鍵字鏈結功能就是將輸入的文章與
27萬條關鍵字字典進行匹配,將必要的地方替換成鏈結。鏈結替換操作實際上只是將特定關鍵字替換成
html
鏈結標籤而已,所以問題就是如何對文章中的關鍵字進行文字替換。
關鍵字鏈結的例子
—hatena diary
是部落格→
hatena diary是部落格
最初的實現
hatena diary
剛剛上線時,該功能並沒有花太多功夫,簡單地採用了正規表示式,將字典中的所有單詞用
or連線做成正規表示式。
(foo|bar|baz| ...)
就是這種正規表示式。假設將文字放在
$text
變數中,那麼把替換選項和替換字串看作表示式的
eval
選項進行組合,變成以下形式就可以了:
use uri::escape;
$text =~
s/(foo|bar|baz)/&replace_keyword($1)/ge;
sub replace_keyword
出問題了!—
—關鍵字字典越來越大
由於關鍵字是使用者建立的,剛上線時單詞數並不多,從資料庫中取出後直接建立正規表示式以實現關鍵字鏈結,這種奢侈的處理也完全沒有問題。但是,隨著關鍵字的數量不斷增加,問題就來了。處理正規表示式要花費很長時間。最耗時的地方有兩處:
u編譯正規表示式的處理;
v用正規表示式進行模式匹配的處理。對於u
,可以預先建立正規表示式並保持在記憶體或磁碟上,即通過快取的方法能夠繞過去了。
對於問題
v,把完成了關鍵字鏈結的正文文字進行快取等處理後,開始時能繞過該問題,但要將新添的關鍵字反映到關鍵字鏈結中,必須花費一定時間重新建立快取,或者從部落格服務的特性上看,多一半文章的訪問量並不大,導致快取很難生效,所以該問題並沒有完全解決。
用模式匹配實現關鍵字鏈結的問題
隨著服務的運營,關鍵字的單詞數超過了
10萬條,而且
hatena
diary
增加的整體訪問量使得關鍵字鏈結的處理次數也增加了許多,系統終於承受不住了。
關鍵字鏈結計算耗費大量時間的原因在於正規表示式的演算法。詳細情況可以參考正規表示式的書籍,簡單來說,正規表示式的模式匹配是基於自動機實現的。而且,
perl
的正規表示式實現採用的是
nfa(
nondeterministic finite automata
,非確定型有窮自動機)。不僅
perl
,實用的語言大多採用了
nfa引擎。
像(foo|bar|baz
)這種模式匹配,
nfa會使用一種簡單的方法,從輸入的開頭嘗試匹配,失敗的話就嘗試下乙個單詞,如果又失敗了,就再次嘗試下乙個單詞。因此,
foo不匹配就嘗試
bar,如果還不匹配,就嘗試
baz……如此迴圈下去。因此,計算量與關鍵字的個數成比例。
服務剛開始時,關鍵字個數很少,相應的計算量也很少,所以沒有發生什麼問題。
本文節選自《大規模
web服務開發技術》一書
圖書詳細資訊
:
什麼是關鍵字鏈結?
什麼是關鍵字鏈結?什麼是關鍵字鏈結?部落格服務hatena diary 支援關鍵字鏈結,這是個很特別的功能。該功能在前面的圖5.3 p.112 的關鍵字鏈結截圖中已介紹過。如圖5.3所示,寫部落格時部分關鍵字會自動加上鏈結,鏈結目標就是該關鍵字的解釋頁面。wiki的實現也能給wiki關鍵字自動加鏈結...
new關鍵字 this關鍵字 base關鍵字
使用new,所做的三件事 1.類是引用物件,引用物件是在堆中開闢空間 在堆中開闢空間 2.在開闢的堆空間中建立物件 3.呼叫物件的構建函式 4.隱藏父類成員 子類的成員可以與隱藏從父類繼承的成員,類似於重寫。public new void sayhello this關鍵字的使用 1.代表當前類的物件...
this關鍵字 static關鍵字
1.當成員變數和區域性變數重名,可以用關鍵字this來區分 this 代表物件,代表那個物件呢?當前物件 this就是所在函式所屬物件的引用 簡單說 那個物件呼叫了this所在的函式,this就代表哪個物件 this也可以用於在建構函式中呼叫其他建構函式 注意 只能定義在建構函式的第一行,因為初始化...