擁抱 Elasticsearch:給 TiDB 插上全文檢索的翅膀

作者介紹:孫曉光,知乎技術平臺負責人,與薛寧(@Inke)、黃夢龍(@PingCAP)、馮博(@知乎)組隊參加了 TiDB Hackathon 2019,他們的項目 TiSearch 獲得了 CTO 特別獎。

“搜索”是大家在使用各種 APP 中非常重要的一個行為,對於知乎這樣以海量優質內容為特色的產品來說,藉助搜索幫助用戶準確、快速地觸達想要尋找的內容更是至關重要。而“全文檢索”則是隱藏在簡單的搜索框背後不可或缺的一項基本能力。

當前我們正逐步將越來越多的業務數據向 TiDB 遷移,目前在 TiDB 上我們只能使用 SQL Like 對內容進行簡單的檢索。但即便不考慮性能問題,SQL Like 仍然無法實現一些在搜索場景下常見的信息檢索需求,例如下圖所示的幾種場景,單純使用 Like 會導致查詢到有歧義的結果或滿足搜索條件的結果無法返回。

擁抱 Elasticsearch:給 TiDB 插上全文檢索的翅膀

當前 TiDB 全文檢索能力的缺失,使得我們依舊需要使用傳統的方式將數據同步到搜索引擎,在過程中需要根據業務特點做大量繁瑣的數據流水線工作維護業務數據的全文索引。

為了減少這樣的重複勞動,在今年 TiDB Hackathon 中我們嘗試為 TiDB 引入“全文檢索”功能,為存儲在 TiDB 中的文本數據提供隨時隨地搜索的能力。以下是最終的效果展示:

擁抱 Elasticsearch:給 TiDB 插上全文檢索的翅膀

方案設計

要在短短一天的 Hackathon 時間內讓 TiDB 中支持全文檢索,難度還是非常大的,於是在最開始的時候,我們就選擇了一條非常穩妥的設計方案——採用整合 Elasticsearch(後續簡稱 ES)的方式為 TiDB 擴展全文檢索能力。


擁抱 Elasticsearch:給 TiDB 插上全文檢索的翅膀

為什麼選擇 ES?一方面我們可以充分利用 ES 成熟的生態直接獲得中文分詞和 query 理解能力。另外生態融合所帶來的強強聯合效應,也符合 TiDB 崇尚社區合作的價值觀。

考慮到工作量,對於全文索引的數據同步方案我們沒有采用 TiKV Raft Learner 機制,也沒有使用 TiDB Binlog 的方式進行同步,而是採用了最保守的雙寫機制直接在 TiDB 的寫入流程中增加了全文索引更新的流程。

擁抱 Elasticsearch:給 TiDB 插上全文檢索的翅膀

架構如上圖所示,TiDB 作為 ES 和 TiKV 之間的橋樑,所有同 ES 的交互操作都嵌入在 TiDB 內部直接完成。

在 TiDB 內部,我們將表額外增加了支持 FULLTEXT 索引的元數據記錄,並且在 ES 上面創建了對應的索引和 Mapping,對於 FULLTEXT 索引中的每一個文本列,我們都將它添加到 Mapping 中並指定好需要的 Analyzer,這樣就可以在索引上對這些文本列進行全文檢索了。

在 ES 的索引的幫助下,我們只需要在寫入數據或者對數據進行更新的時候在 ES 的索引上進行對應的更新操作,就保持 TiDB 和 ES 數據的同步。而對於查詢,現在流程如下:

  1. TiDB 解析用戶發送的 Query。
  2. 如果發現該 Query 帶有全文檢索的 hint,TiDB 則會將請求發給 ES,使用 ES 索引查詢到記錄主鍵。
  3. TiDB 拿到所有記錄主鍵之後,在 TiDB 內部獲取實際的數據,完成最終的數據讀取。
  4. TiDB 將結果返回給用戶。

未來規劃

Hackathon 短短的 24 小時,讓我們驗證了整合 TiDB 和 ES 的可能性,當然,我們不會滿足於這套雙寫的方案。未來我們會參考 TiFlash,基於 Raft Learner 實時將數據變更同步給 ES,將 TiDB 打造成一個真正的能支持實時全文檢索的 HTAP 數據庫,如下圖所示:

擁抱 Elasticsearch:給 TiDB 插上全文檢索的翅膀

使用 Raft Learner,對於寫流程:

  • TiDB 會直接將數據寫給底層的 TiKV。
  • TiKV 會通過 Raft 協議將寫入數據同步到 ES Learner 節點,通過該 Learner 節點寫入到 ES。

對於讀流程:

  • TiDB 解析到用戶發過來的 Query 帶有全文檢索的 hint。
  • TiDB 將請求發給 ES Learner 節點。
  • ES Learner 節點首先通過 Raft 協議來確保節點上面有了最新的數據,並且最新的數據已經寫入到 ES。
  • ES Learner 節點通過 ES 的索引讀取到對應的記錄主鍵,返回給 TiDB。
  • TiDB 使用記錄主鍵獲取到完整的數據,並返回給客戶端。

可以看到,相比於之前讓 TiDB 雙寫到 ES 和 TiKV 的方案,在寫入上面,TiDB 並不需要跟 ES 進行交互,而在讀取方面,通過 Raft 協議,TiDB 也能保證從 ES 讀取到最新的數據,保證了數據的一致性。

當然,要實現上面的功能,我們也需要更多的幫助,我們希望能夠跟社區小夥伴一起,一起完成這個非常酷的特性。

寫在最後

得益於個人在知乎搜索團隊的短暫經歷,對搜索的價值和業務接入搜索的工作量有過很直觀的感受。在越來越多的數據存在於 TiDB 的時代,隨時可以對業務數據的某些字段進行全文檢索的價值很大。這個價值不但體現在能夠實現以往 SQL 難以做好的一些事情,更大的意義是將全文檢索的能力以接近 free 的方式提供給業務方,給用戶搭建起一座連接關係型數據庫與搜索引擎的橋樑,做到隨時寫入,隨時搜索。如果你也有這方面的想法,歡迎郵件聯繫我 [email protected]

原文閱讀:https://pingcap.com/blog-cn/fulltext-search-with-tidb-and-elasticsearch/


分享到:


相關文章: