淺談es的原理、機制 ,IK分詞原理
阿新 • • 發佈:2019-01-14
1、分散式的架構es都有哪些機制?
1、主備
primary shard 的副本 replica shard
primary shard不能和自己的replica shard放在同一個節點上、
2、容錯
使用選舉機制
master node宕機,選舉master node,提升replica 為primary、
宕機的node重啟資料恢復
2、IK分詞原理
IK 分詞器,
1、詞典樹Tire Tree的構建,即將現在的詞典載入到一個記憶體結構中去
2、詞的匹配查詢,就是切詞
3、歧義判斷,即對不同切分方式的判定,哪種應是更合理的
2.1、詞典樹的構建
class DictSegment implements Comparable<DictSegment>{
//公用字典表,儲存漢字
private static final Map<Character , Character> charMap = new HashMap<Character , Character>(16 , 0.95f);
//陣列大小上限
private static final int ARRAY_LENGTH_LIMIT = 3;
//Map儲存結構
private Map<Character , DictSegment> childrenMap;
//陣列方式儲存結構
private DictSegment[] childrenArray;
//當前節點上儲存的字元
private Character nodeChar;
//當前節點儲存的Segment數目
//storeSize <=ARRAY_LENGTH_LIMIT ,使用陣列儲存, storeSize >ARRAY_LENGTH_LIMIT ,則使用Map儲存
private int storeSize = 0;
//當前DictSegment狀態 ,預設 0 , 1表示從根節點到當前節點的路徑表示一個詞
private int nodeState = 0;
……
ARRAY_LENGTH_LIMIT 的閥值來判斷,資料較小存在陣列,資料較大,存在HashMap 中;
如資料較小,存陣列,採用二分查詢的方式、
若資料較大,存在HashMap中時候,使用遞迴呼叫寫入字典樹,直接查詢的方式;
private synchronized void fillSegment(char[] charArray , int begin , int length , int enabled){
……
//搜尋當前節點的儲存,查詢對應keyChar的keyChar,如果沒有則建立
DictSegment ds = lookforSegment(keyChar , enabled);
if(ds != null){
//處理keyChar對應的segment
if(length > 1){
//詞元還沒有完全加入詞典樹
ds.fillSegment(charArray, begin + 1, length - 1 , enabled);
}else if (length == 1){
//已經是詞元的最後一個char,設定當前節點狀態為enabled,
//enabled=1表明一個完整的詞,enabled=0表示從詞典中遮蔽當前詞
ds.nodeState = enabled;
}
}
}
2.2、切詞
切詞的2種方式
1、非smart模式
IK分詞輸出所有分詞、
2、smart模式
IK分詞器則會根據內在方法輸出一個認為最合理的分詞結果,這就涉及到了歧義判斷、
、
smart模式 張三 | 說的 | 確實 | 在理
非smart模式 張三 | 三 | 說的 | 的確 | 的 | 確實 | 實在 | 在理
IK中預設用到三個子分詞器,
LetterSegmenter(字母分詞器),CN_QuantifierSegment(量詞分詞器),CJKSegmenter(中日韓分詞器)。分詞是會先後經過這三個分詞器,我們這裡重點根據CJKSegment分析。其核心是一個analyzer方法。
public void analyze(AnalyzeContext context) {
…….
//優先處理tmpHits中的hit
if(!this.tmpHits.isEmpty()){
//處理詞段佇列
Hit[] tmpArray = this.tmpHits.toArray(new Hit[this.tmpHits.size()]);
for(Hit hit : tmpArray){
hit = Dictionary.getSingleton().matchWithHit(context.getSegmentBuff(), context.getCursor() , hit);
if(hit.isMatch()){
//輸出當前的詞
Lexeme newLexeme = new Lexeme(context.getBufferOffset() , hit.getBegin() , context.getCursor() - hit.getBegin() + 1 , Lexeme.TYPE_CNWORD);
context.addLexeme(newLexeme);
if(!hit.isPrefix()){//不是詞字首,hit不需要繼續匹配,移除
this.tmpHits.remove(hit);
}
}else if(hit.isUnmatch()){
//hit不是詞,移除
this.tmpHits.remove(hit);
}
}
}
//*********************************
//再對當前指標位置的字元進行單字匹配
Hit singleCharHit = Dictionary.getSingleton().matchInMainDict(context.getSegmentBuff(), context.getCursor(), 1);
if(singleCharHit.isMatch()){//首字成詞
//輸出當前的詞
Lexeme newLexeme = new Lexeme(context.getBufferOffset() , context.getCursor() , 1 , Lexeme.TYPE_CNWORD);
context.addLexeme(newLexeme);
//同時也是詞字首
if(singleCharHit.isPrefix()){
//字首匹配則放入hit列表
this.tmpHits.add(singleCharHit);
}
}else if(singleCharHit.isPrefix()){//首字為詞字首
//字首匹配則放入hit列表
this.tmpHits.add(singleCharHit);
}
……
}
2.3、歧義判斷
IKArbitrator(歧義分析裁決器)是處理歧義的主要類。