一、線上庫不支援線上複雜查詢
做線上業務的開發者經常會碰到這樣的難題:線上資料庫上面運作稍微複雜點的查詢,線上業務就挂了!不管是單機資料庫如MySQL、PG,還是分布式資料庫,HBase、MongoDB、Cassandra都有這個問題。下面,本文就以HBase為例對該問題進行說明,其他庫原理類似。
HBase作為海量線上存儲引擎,被廣泛應用于推薦、風控、物聯網、畫像、表單等大資料場景。Phoenix作為HBase的SQL層,極大降低了使用者使用門檻,并且實作了二級索引、加鹽表、動态列等大量實用功能。HBase底層存儲基于LSM,LSM能将業務的随機寫轉為順序寫,能有效提升寫吞吐,但是其查詢隻适合于Rowkey的字首比對,查詢模式單一;Phoenix二級索引,底層是跟原表關聯的索引表,同樣也是字首比對,一個表可以有多個索引,這樣可以增加查詢模式,但是索引數目不能太多,否則寫放大的問題會比較嚴重。
對于更加複雜的查詢場景,比如表單、日志查詢裡面的模糊查找,使用者畫像裡面的随機條件組合等等,HBase + Phoenix的組合就不能支援。該問題是基于LSM的NoSQL線上資料庫的通用問題,除了HBase,Cassandra、LevelDB、RocksDB、MongoDB引擎等都有相同的問題。
有開發者選擇在備庫上做複雜查詢,不過前面提到線上庫本身的查詢能力往往有限,要麼很慢,要麼就查不出來,滿足不了線上複雜查詢的實時性要求。
二、雙寫遇到的問題

為了解決問題1,使用者自然會想到借助檢索引擎,比如ES、Solr、Lucene等來解決該問題。不少使用者選擇的是雙寫的方式,也就是每一條記錄同時寫線上庫和檢索引擎,該方式看起來簡單,但實際使用過程中問題很多。我們了解到的case,把這套方案解決較好的客戶往往都是要投入月級别的時間和大量人力。下面以雙寫HBase和Solr為例,舉幾個使用者遇到比較多的問題。
- 一緻性難以保證
雙寫很難保證線上庫跟檢索引擎的一緻性。比如,兩個連結并發雙寫,并且有修改的操作,那麼很難保證HBase中同一字段的寫入順序跟Solr中同一個doc的修改順序一緻,那HBase和Solr中資料就出現了不一緻,而且出現問題很難排查;另外,線上庫往往隻需要儲存最近一段時間的資料,超過TTL的資料會被自動清理掉,而Solr中同樣會有這個需求。但是HBase是按照KV做TTL的,Solr是按照doc,那兩者在做資料清理的時候同樣會出現不一緻。不一緻的場景有很多,這裡就不一一介紹了。
- 寫入性能下降
相同配置下,HBase的吞吐要比Solr高很多,這源于軟體設計的出發點不同,優化的方向不同等諸多因素。如果雙寫,那勢必會導緻Solr的寫吞吐限制了HBase的寫吞吐。
- 曆史資料的同步
雙寫隻是解決了新資料的問題,對于曆史資料則不适用,使用者需要自己解決曆史資料批量同步問題。特别是,對于不能停機的場景,在曆史資料rebuild過程中,如何解決跟新資料跟曆史資料互相覆寫的問題,也是十分棘手的問題。
- 備援存儲空間
檢索引擎專門解決索引問題,其資料存儲格式要比線上庫要更複雜,一份線上庫的資料在檢索引擎中可能需要存儲多份,比如原始資料存儲,反向索引存儲,為提升聚合和排序的列存DocValue的存儲。那麼,勢必有存儲備援的問題,如何降成本也是一大挑戰。
- 穩定性
雙寫要求HBase和Solr同時保證穩定性,如果Solr出現故障,寫流程會被block住,對線上業務造成影響。
三、HBase + Solr易用性不足
阿裡雲HBase Solr全文檢索引擎,采用在系統層做資料轉換和同步的方式一站式解決了使用者使用雙引擎遇到的大部分問題。但是,試用過的使用者會有一個體會,就是使用太靈活了,步驟也比較繁瑣,容易出問題,如果不是資深玩家難以駕馭。下面舉幾個使用者痛點:
- 使用門檻高
使用者需要同時了解HBase、Solr、Indexer(資料同步服務),同時操作HBase Shell,Indexer指令行,Solr界面三個途徑才能把流程走通。
-
Schemaless的HBase跟強Schema的Solr資料類型
難以保證對齊
首先,使用者要自己定義從HBase column到Solr field的映射;其次,使用者要自己保證明際寫入到HBase中的類型正确。比如HBase中一個列對應Solr中一個long類型,因為HBase API并不檢查使用者實際寫入的數值是否合法,導緻寫入HBase成功,但是同步到Solr是通不過的。這就要求使用者要自己基于HBase API寫一套類型檢查系統,費時費力。
- HBase + Solr對于資料備援存儲的問題解決不友好
使用者需要自己決定Solr中是否開啟stored,docValued選項,對于隻開啟indexed選項的Field,使用者可以通過回讀HBase的方式來拿到最終結果資料,而對于開啟了stored或者docValued的Field,直接從Solr中傳回結果性能會更好。這套優化的邏輯需要使用者自己管理和實作。
四、SearchIndex靈活易用一體化線上庫引擎
SearchIndex是阿裡雲HBase SQL(Phoenix)基于HBase + Solr雙引擎的新的索引實作,其架構如上圖所示。Phoenix層将SQL(DDL、DML)語句轉化為對HBase和Solr的具體操作,SearchService負責索引同步,一緻性,中繼資料管理等。
SearchService内部會統一管理HBase中TimeStamp和Solr中DocVersion的對應關系,來實作最終一緻性。簡單來說,Solr一行資料的DocVersion等于目前已被同步的HBase對應行各個column的TimeStamp最大值,在解決亂序時,如果前面新的cell已經被同步了,老的cell則被直接丢掉即可。而對于TTL問題,我們實作了基于行的HBase Compaction機制,來保證一緻性。
SearchIndex解決了前面提到的所有問題,使用者隻需要幾分鐘,幾條SQL語句就可以跑通整個流程,可參考
快速開始文檔;Phoenix強類型直接映射Solr類型,并支援分詞、Array等複雜類型;自适應回查的優化政策更好解決了資料備援存儲問題。相比于HBase Solr全文檢索引擎,大大提高了易用性,并且覆寫絕大部分的場景和需求。但目前SearchIndex還不能完全取代HBase + Solr,對于資深玩家,比較喜歡直接寫HBase API和Solr API帶來的靈活性,仍然可以選擇使用HBase Solr全文檢索引擎的方式。
SearchIndex是針對阿裡雲公共雲客戶定制開發的一體化雲原生線上NoSQL資料庫引擎,具有低成本、靈活、易用、穩定等特點,已經被用于物流巴槍、線下支付表單、電商表單、醫藥實驗日志等行業和場景,使用者資料量已達數百億規模,經曆過雙十一的考驗。使用者第一步可以隻購買HBase執行個體,全文服務和SQL服務可以後續單獨開通,單獨更新管理。歡迎感興趣的開發者共同交流。