自定義查詢系統架構設計分析
背景
最近參與某新自定義查詢系統開發,系統是鋒哥設計的,核心代碼也是鋒哥寫的。作為一個搬磚者自下而上的分析學習一下大神的系統設計。文中的談到架構設計內容是根據對代碼理解重新整理出來的,不代表系統的實際架構和實現。同時由於業務和技術的復雜性及其他原因,不對實現細節作說明。
設計場景
在該系統之前已經有兩個自定義查詢系統,一個為競爭對手的CS系統,一個為我司開發的BS系統。兩個系統均用了MS SQLSERVER為數據存儲和查詢引擎,實現的業務功能很多,同時也有比較嚴重的性能問題。新系統的主要使命是用新技術提高自定義查詢性能,改善可用性,同時對飆競爭對手的系統。因此也有很多設計上不合理但必須的功能。
必備知識
系統中用到了一些新技術,這些新技術或者非主流的技術是該系統實現的基石,這里做一個簡單介紹。
- Elasticsearch全文搜索引擎。需要對ES的DSL查詢語言和數據模型有深入的理解。
- FreeMarker 模板引擎。前端界面及大量的模型類和數據轉換類使用該技術自動生成。
- layui 前端UI組件。采用前后端分離設計,界面及一些重要的組件用此技術實現,並做了一些改造。
- RocketMQ 消息隊列,在該系統中做數據同步使用。
邏輯架構
系統的主要目的是將若干業務系統的數據信息,清洗轉換匯聚到ES中,利用ES在查詢方面的性能優勢,來實現自定義查詢。系統邏輯上大概可以分為以下幾個模塊:
數據模型
-
什么是數據模型?
數據模型出現的本質原因是RDBMS與ES的數據建模方式不同,需要一套對應規則將各業務系統的數據庫表及數據對應到ES中。本系統中數據模型是什么呢?不是代碼,是四張核心的excel。這四張excel是本系統的靈魂和精華所在,10萬行代碼本質上就是圍繞這四張excel編寫的,同時excel中的數據固化到元數據庫中。 -
數據模型解決了什么問題?
- 數據從哪里來的問題
定義了從哪些子系統中獲取什么數據及數據的關聯方式 - 數據到哪里去的問題
定義了在ES中數據存儲到哪幾個索引、類型和數據文檔嵌套方式 - 查什么數據的問題
定義了系統中可以查詢哪些字段和展示哪些數據字段 - 怎么查數據的問題
定義了數據字段在ES中的路徑和不同字段類型在ES中使用的查詢方式及結果集處理方式
- 數據從哪里來的問題
數據同步
通過以下幾個主要的步驟實現數據從業務庫到ES中的同步:
- 業務系統中埋點或者數據庫觸發器將要同步的元信息推送到MQ
- 消費端(新自定義查詢)將要同步的數據以任務的形式落庫
- 新自定義查詢系統定時的根據任務從其他系統拉取數據
- 將拉取的數據做清洗轉換導入到ES集群
數據清洗
系統通過以下幾個步驟實現數據的裝載和轉換:
- 根據同步任務,各批量裝載器實現業務數據的加載
- 將數據轉換的中間結果落盤
- 從磁盤中讀出中間數據,各轉換器轉換后,導入到ES。
查詢引擎
-
什么是查詢引擎?
查詢引擎主要將前台頁面選擇的條件和展示字段、排序方式、分頁方式、數據合並方式等在后台轉換成ES的DSL查詢語言並查詢出結果。是系統最重要的模塊,同時也是代碼邏輯最復雜的模塊。 -
查詢條件的組合方式
從組合方式上來說,查詢條件有與、或、非、異或、全或幾種組合,分別對應着DSL的 must、should、must_not 和其組合。 -
值的比較方式
從值的比較方式上來說,主要有精確匹配、范圍匹配、前綴匹配、模糊匹配等,分別對應着DSL的term、terms、range、prefix、wildcard等 -
ES的數據建模方式
從ES的數據建模方式來看,查詢主要可以分為嵌套查詢、父子查詢、子父查詢、父子+嵌套查詢等
系統主要以流水線得思想將一個復雜的查詢拼裝,分配給各組件完成,並統一組裝,主要有嵌套查詢流水線、父子查詢流水線、子父查詢流水線等
模板引擎
模板引擎主要將大量重復勞動或者需要靈活變動或者特殊對應關系的代碼用模板生成,主要生成前端Html、pojo類,mapper映射和其他元數據磁盤緩存等。
對外服務
- 對外服務主要提供了將ES中的數據以某種方式輸出,提供給外部系統。
系統總結
首先,優點:
- 實現了系統的使命,查詢性能有很大提高,且由於ES的橫向可擴展性,數據量增大也能保證基本查詢性能。
- 引入了新技術新模式,為解決類似問題提供了另外一條思路。且對ES的深入使用,應該是走到了研發中心各團隊的前面。
- 其設計思想和部分代碼可以復用借鑒到其他項目。
其次,缺點:
- 不僅要有新技術新模式,更要引入新思想新用法。還按照傳統的方法去使用ES,引入了幾個疑難問題,比如復雜排序問題和深分頁問題(解決方法參見本人博客)。
- 設計思想的執行和代碼質量因為交付壓力大打折扣,代碼上有很強的業務耦合,比較難做到直接復用。
- 數據同步設計有待商榷,比如數據同步的及時性和穩定性及對其他系統的壓力。
- 查詢引擎代碼有不少重復且后續邏輯有點混亂,耦合度高。
- 對ES等新技術的特性研究還不夠,掉入了一些坑里。