1 簡介
1.1 背景
《搜索引擎onesearch 1.0-設計與實現.docx》介紹了1.0特性,搜索schema,agg,表達式搜索映射,本文介紹onesearch 2.0 新特性, 參考第2節 規劃特性與發布計劃
1.2 關鍵詞
? 文檔 Document
elasticsearch 一行數據稱為文檔,需要注意與文件/文檔區分,有沖突的地方用“ES文檔”區分
? 索引schema
相當于關系數據庫的schema,xml格式,定義索引的字段,類型,還有搜索策略,分詞等搜索相關屬性
? 搜索/過濾
elasticsearch查詢分兩部分,搜索和過濾,搜索計算文檔與搜索詞相似(匹配)度,得出分數排序,分數越高相似度越高,排序也靠前;過濾相當于sql的where,結果是true或者false
? 查詢對象裝配映射
elasticsearch es dsl 查詢功能非常豐富,可調參數多, 提供精準細致的搜索調整,但也很難用,更難復用,onesearch設計裝配映射組件支持通用表達式轉換esdsl,用戶只需編寫通用表達式,如,((f1=‘a’or f2=’b’) and f3=‘c’)) 即可實現搜索過濾,類似elasticsearch自身也提供了sql查詢功能,大大降低開發難度,同時具備高復用性
1.3 參考資料
再見esdsl, elasticsearch擴展使用通用表達式搜索
分布式datax架構設計 分布式文檔索引全量增量使用分布式datax
分布式 dataX 詳細 (落地) 設計
tika原理源碼分析
2 特性
2.1 大規模/分布式文件索引
? 文檔抓取
1) 文檔內容抓取組件,metadata(base+extras)+content
2) 抓取組件隔離機制
? 索引引擎,基于分布式dataX,支持批量/增量
2.2 精確搜索/多元搜索
? 裝配/映射 增加支持query,目前已支持映射為filter
1) full text查詢映射策略
match
query_string
2) 高亮
3) 返回字段,source/store
4) 批量操作
? springboot starter
3 搜索特性

1. 搜索框,用戶輸入搜索詞
2. 高級搜索,構建搜索過濾表達式,如,(x==’a’ and (y=’abc*’ or z > 100))
3. 統計區,聚合搜索功能,針對搜索內容統計,如文檔的類型計數,一般展示不超過3項,多于3行點擊”》”查看
4. 標題/內容,標準搜索返回展示,帶高亮
5. 文檔extras屬性(TBD),文檔的專有屬性,如,視頻的播放時間
4 onesearch總體架構

? schema模塊,定義索引字段,索引策略,搜索策略等,管理索引及其搜索特性
? 聚合搜索(agg)模塊,基于schema模塊,支持xml定義agg,零編碼增加agg主題
? 查詢模塊,負責構建通用表達式(如,((f1=‘a’or f2=’b’) and f3=‘c’)),作為搜索輸入條件代替esdsl
? 映射引擎,映射通用表達式為最優的es dsl,支持=,!=,like,in,range,prefix,not/and/or,大小括號,點(.)等操作符映射,解決es dsl難使用,難復用的痛點
? 抽象搜索引擎接口,無縫接入不同的搜索引擎,如,elasticsearch,opensearch,solrcloud等,更可同時使用多種引擎
? 同步,全量同步/增量同步,接入分布式dataX
5 組件架構
下圖是onesearch 2.0組件的架構視圖

抓取器 文檔庫分片/內容抓取,引入tika
索引組件 接入分布式dataX,實現為dataX的reader/writer,實現高吞吐,分布式的文檔索引;依賴setl讀取文件目錄(數據庫表);依賴搜索引起索引服務
搜索引擎 支持批量操作的索引服務,自定義索引策略,索引模式
6 全文搜索-esdsl裝配映射組件
2.0 對裝配映射組件重構,支持完整的映射,增加了query,返回字段支持;1.0 支持 filter,高亮,分頁,排序
? 裝配/映射抽象模型

裝配映射組件設計原理:
搜索請求由多個模塊有機組合而成,如,sql,選擇字段(select), from, where3塊組成
SearchAssemble 裝配器,調用SearchBlockMapping生成模塊,組裝成可執行搜索請求,模板變量T是可執行請求類型
SearchBlockMapping 模塊的映射器,接受SerchConfigBean,映射為搜索請求的模塊,模板變量T是映射生成結果類型,P接受配置類型,
OperatorMapping 表達式映射器
? elasticsearch實現

基于模板的裝配/映射實現
elasticsearch的esdsl有由以下塊(Block)構成:
查詢映射塊,接收QueryPropertis配置,QueryPropertis有兩個映射策略,Match和Query String,
查詢映射塊調用filter映射塊,構建filter部分,filter映射塊調用表達式映射塊轉換filter表達式為esdsl,組成filter塊,再嵌入到查詢塊構建完整的查詢映射塊;查詢映射塊模板變量T是字符串(json)類型,P類型是QueryPropertis
選擇字段塊,目前實現source過濾方式,接受SourceFieldsProperties配置,store方式暫沒實現
Agg映射塊 映射后端agg schema配置為AggregationBuilder,即模板變量T是AggregationBuilder
高亮映射塊 模板變量T是HighlightBuilder,即映射生成HighlightBuilder
其他,排序塊,分頁塊比較簡單沒有實現為塊映射
TemplateESSearchAssemble 裝配實現,T是SearchSourceBuilder, 即裝配返回SearchSourceBuilder
? 默認即可用
裝配映射配置復雜,用戶使用比較麻煩,涉及細致的調參,本著默認即可用的理念,組件提供默認的配置
1. 選擇字段塊,source字段方式,排除_content字段(如果有)
2. query, match查詢,text字段匹配搜索詞,其他字段用于filter表達式
3. 高亮,text字段設置高亮,高亮優先,_content字段排除在返回中,只有高亮,但高亮默認設置noMathcSize屬性
7 索引組件

reader/transformer/writer datax作業組件組合,reader讀取文檔內容,屬性+內容的形式;writer依賴搜索引擎
本版本文檔目錄從數據庫讀取,setl-data提供統一的dao接口,無縫切換不同的驅動;marker支持輪詢增量的組件;數據庫支持事務log,可使用setl-data的cdc組件
file-storage 文檔(流)載入組件,支持多庫多協議
document-extractor 文件解釋內容抓取,核心使用tika
7.1 文件存取組件(file-storage)

文檔索引首先需要載入文檔,文檔載入兩個關鍵,文檔地址和讀寫協議
file-storage提供統一FileService接口,橋接地址和協議,提供多庫多協議讀取能力;
組件根據url,如,schema://rootUrl/, 選擇對應FileService
組件目前支持本地磁盤,smb,ali oss,ftp,minio
7.2 抓取器組件(extractor)

組件使用tika解釋和抓取文檔內容
IndexingDocument 索引資源bean,屬性+內容,索引文檔Id對于后期增量同步很重要,提供兩種id生成,url和文檔id,其中文檔id為了支持多庫,增加文檔庫編號sn字段,組成”sn-id“作為索引id
? 內容處理器

tika很好的解釋文檔,抓取文檔內容,但留下一個問題,BodyContentHandler實現是基于內存的,需要用戶設置write-limit限制內存使用,OOM問題交給用戶了。
文檔索引,大文件會產生大容量內容,同時datax reader/transformer/writer鏈路長,內存使用時間長,write-limit設置顯得困難,內容容量大,內存使用高,容易出現oom,只能降低并發度,因此需要實現基于磁盤的內容處理器
BodyContentHandler依賴Writer寫入內容,基于文件內容處理器核心是實現FileBasedWriter,使用臨時文件,reader實例化,載入文檔,datax writer寫入es,然后釋放流和刪除臨時文件
寫入階段仍然需要流生成內存字節,但縮短內存使用時間
7.3 轉換組件(transformer)

轉換的設計參考 datax基于規則轉換(RBT)組件+圖數據庫間同步設計與實現
StreamRecord,支持大容量文本以文件流形式傳遞
SyncStreamRecord 攜帶Marker,參考增量索引
7.4 全量文檔索引
7.4.1 文檔分片遍歷
接入分布式dataX,需要分片的策略,無重復無遺漏的遍歷所有的文檔
a) 數據庫分片
數據表的分片
b) 目錄分支分片
節點分配一個分支(路徑),該策略簡單,但容易出現分配傾斜
c) 文件名哈希
所有節點遍歷整個文檔目錄,只處理分派給自身的hash分片,該策略分配比較均衡,需要完整統一的文件名hash實現,能處理不同語言,特殊字符的hash計算
7.4.2 Reader
Reader 分段,分頁,抓取器->StreamRecord
7.4.3 Writer
Writer Record->IndexingDocument->索引服務->寫入elasticsearch
Writer依賴onesearch組件,onesearch提供的索引服務,因此writer實現非常簡單

索引使用StreamRecord傳遞數據,根據onesearch getter機制獲取索引屬性,實現StreamRecordValueGetter
關于onesearch getter組件參考《搜索引擎onesearch 1.0-設計與實現.docx》
7.4.4 技術架構
批量分布式索引技術架構

client 負責寫入任務組分片;觸發 worker 執行;client 可集成到管理臺;作業監管,檢測作業完成,清理作業環境
watcher 作業統計,輸出統計;按作業分片觀測和聚合計算; watcher 可集成到管理臺
worker 分配分片;任務(組)執行,任務組執行統計
8 增量索引
8.1 標記組件
標記(marker/xmarker)組件用于資源切分, 如,數據表/文件,
marker使用表里的單調遞增字段,每次批處理升序排序的數據,處理完記錄最后一個,即最大value,下次獲取數據>value獲取未處理數據,這種方式會重復處理數據,應用需要識別或支持冪等
xmarker增加hash值,支持橫向切分

8.2 增量分片
全量是有上下邊界的大表,分頁即分片,而增量是有下屆沒有上界的表,也可以使用與全量一樣的分片,最上面的分片無上界,這里引入另一種方式,hash分片,worker分配取模數,worker獲取文件數據,使用設定的字段取模,只處理等于分配的hash的記錄,組件使用updateTime取模,這種適用于增量,分片不用改變,而增量的分片一次性,每次運行前重新計算分片上下界
8.3 增量reader/writer
Reader 讀取文檔記錄,構建SyncStreamRecord,攜帶XMarker
Writer 與全量同一個writer,判斷record類型,取出XMarker,更新marker
8.4 技術架構
分布式架構使用分布式datax,與全量基本一致架構,上圖用另一種表達方式,與全量不同,增量client是定時任務,全量是一次性執行

9 spring boot starter

spring boot starter自動配置組件
ESClientBeanConfig elasticsearch rest client 構建和初始化,索引和搜索均使用到
SchemaBeanConfig 索引schema, 序列化器,索引和搜索均使用到
ESIndexServiceBeanConfig 引擎層索引服務/文檔服務
DocumentServiceBeanConfig 服務層文檔服務,getter庫
ESSearchMappingBeanConfig elasticsearch 搜索裝配映射bean,包括裝配器,高亮塊映射,查詢塊映射,operator庫等
ESSearchServiceBeanConfig 引擎層搜索服務
SearchServiceBeanConfig 服務層搜索服務
10接口
10.1 datax作業管理api

寫入/重置/刪除 分布式datax作業,client/worker/watcher
10.2 通用作業管理api
11工程
? 索引組件

indexing-document 文檔索引,規劃增加數據庫索引組件
indexing-document-common 公共常量定義,公共組件
indexing-document-datax 單機datax工程
indexing-document-extractor 抓取器,解釋文檔,抓取文檔屬性和內容
indexing-document-reader 全量reader
indexing-document-syncreader 增量reader
indexing-document-reader 轉換
indexing-document-reader writer,支持全量和增量
? onessearch

12 zookeeper結構

warcher 域內唯一,處理域內所有作業的統計,使用時間槽方式定時調度
worker 全量/增量工作節點,分片是taskgroup
client 域內唯一,只有增量client定時執行,全量不需要