您好,登錄后才能下訂單哦!
棄用MongoDB使用ES后的好處有哪些,針對這個問題,這篇文章詳細介紹了相對應的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
序言
圖示:MongoDB與Elasticsearch熱度排名
圍繞兩個話題展開:
為什么要從MongoDB遷移到Elasticsearch?
如何從MongoDB遷移到Elasticsearch?
現狀背景
MongoDB本身定位與關系型數據庫競爭,但工作中幾乎沒有見到哪個項目會將核心業務系統的數據放在上面,依然選擇傳統的關系型數據庫。
1、項目背景
公司所在物流速運行業,業務系統復雜且龐大,用戶操作者很多,每日有大量業務數據產生,同時業務數據會有很多次流轉狀態變化,為了便于記錄追蹤分析,系統操作日志記錄項目應運而生,考慮到原有的日均數據量,操作日志數據基于MongoDB存儲。
操作日志記錄系統需要記錄兩種數據,如下說明:
1)變更主數據,什么人在什么時間在系統哪個模塊做了什么操作,數據編號是什么,操作跟蹤編號是什么。
{ "dataId": 1, "traceId": "abc", "moduleCode": "crm_01", "operateTime": "2019-11-11 12:12:12", "operationId": 100, "operationName": "張三", "departmentId": 1000, "departmentName": "客戶部", "operationContent": "拜訪客戶。。。" }
2)變更從數據,實際變更數據的變化前后,此類數據條數很多,一行數據多個字段變更就記錄多條。
[ { "dataId": 1, "traceId": "abc", "moduleCode": "crm_01", "operateTime": "2019-11-11 12:12:12", "operationId": 100, "operationName": "張三", "departmentId": 1000, "departmentName": "客戶部", "operationContent": "拜訪客戶", "beforeValue": "20", "afterValue": "30", "columnName": "customerType" }, { "dataId": 1, "traceId": "abc", "moduleCode": "crm_01", "operateTime": "2019-11-11 12:12:12", "operationId": 100, "operationName": "張三", "departmentId": 1000, "departmentName": "客戶部", "operationContent": "拜訪客戶", "beforeValue": "2019-11-02", "afterValue": "2019-11-10", "columnName": "lastVisitDate" } ]
2、項目架構
項目架構描述如下:
業務系統新增或者編輯數據,產生操作日志記錄發送到Kafka集群,基于dataid字段作為key;
新增或編輯數據實際存儲到MySQL數據庫;
canal集群訂閱MySQL集群,按照業務系統模塊配置監控的數據庫與表;
canal將監控到的變更業務數據發送到Kafka集群,基于dataid字段作為key;
操作日志系統從Kafka獲取主記錄數據與從記錄數據;
操作日志系統寫入數據到MongoDB,同時需要反查詢。
圖示:操作日志記錄業務流程說明
3、MongoDB架構
集群架構說明:
服務器配置8c/32gb/500gb ssd;
Router路由服務器部署了3個節點;
Config配置服務器部署了3個節點;
Shard分片服務器部署了9個節點;
主操作記錄設計3個分片;
從操作記錄設計3個分片。
問題說明
MongoDB的信徒們可能懷疑我們沒有使用好,或者我們的運維能力欠缺,或者認為我們有Elasticsearch的高手在。不是這樣的,棄用MongoDB選擇Elasticsearch其實并非技術偏見問題,而是我們的實際場景需求,原因如下:
1、搜索查詢
MongoDB內部采用B-Tree作為索引結構,此索引基于最左優先原則,且必須保證查詢順序與索引字段的順序一致才有效,這個即是優點,但在現在復雜業務場景也是致命的;
業務系統查詢操作日志記錄會有很多過濾條件,且查詢條件是任意組合的,現有MongoDB是不支持的,或者說所有關系型數據庫都不支持,如果要支持,得創建好多組合的B+數索引,想法很不理智,這個我們已經在《DB與ES混合之應用系統場景分析探討》文中探討過,詳細可以閱讀;
同時主記錄與從記錄中有很多字符類的數據,這些數據查詢即要支持精確查詢,也要支持全文檢索,這幾個方面MongoDB功能很單一,性能也很糟糕,業務系統查詢時經常超時,反倒是Elasticsearch非常合適。
2、技術棧成熟度
分片與副本實現問題,MongoDB集合數據在設計時是需要綁定到具體的機器實例的,哪些分片分布在哪些節點上,哪些副本分布在哪些節點上,這些都需要在配置集群時就要綁定死,跟傳統的關系型數據庫做分庫分表本質上沒有什么兩樣,其實現在很多數據產品的集群還是這種模式偏多,比如Redis-cluster,ClickHouse等。而Elasticsearc的集群與分片和副本沒有直接的綁定關系,可以任意的平衡調整,且節點的性能配置也可以很容易差異化;
操作日志數據量增加很快,單日寫入超過千萬條,不用多久,運維人員就需要對服務器進行擴容,且相對Elasticsearch復雜很多;
MongoDB單集合數據量超過10億條,此情況下即使簡單條件查詢性能也不理想,不如Elasticsearch倒排索引快;
公司對于ES與MongoDB技術棧的經驗積累不同,Elasticsearc在很多項目中運用,非常核心的項目也是大量運用,對于其技術與運維經驗更豐富,而MongoDB如果除去核心業務場景,幾乎找不到合適的切入口,實際沒有人敢在核心項目中使用MongoDB,這就很尷尬。
3、文檔格式相同
MongoDB與Elasticsearch都屬于文檔型數據庫 ,Bson類同與Json,_objectid與_id原理一樣,所以主數據與從數據遷移到Elasticsearch平臺,數據模型幾乎無需變化。
遷移方案
異構數據系統遷移,主要圍繞這兩大塊內容展開:
上層應用系統遷移,原來是針對MongoDB的語法規則,現在要修改為面向Elasticsearch語法規則;
下層MongoDB數據遷移到Elasticsearch。
1、Elastic容量評估
原有MongoDB集群采用了15臺服務器,其中9臺是數據服務器,遷移到Elastic集群需要多少臺服務器?我們采取簡單推算辦法,如假設生產環境上某個MongoDB集合的數據有10億條數據, 我們先在測試環境上從MongoDB到ES上同步100萬條數據,假設這100萬條數據占用磁盤10G,那生產上環境上需要1個T磁盤空間,然后根據業務預期增加量擴展一定冗余。根據初步評估,Elastic集群設置3臺服務器, 配置8c/16g內存/2T機械磁盤。服務器數量一下從15臺縮減到3臺,且配置也降低不少。
2、Elastic索引規則
系統操作日志是時序性數據,寫完整后基本上無需再次修改。操作日志記錄查詢主要是當月的居多,后續的歷史性數據查詢頻率很低,根據評估,核心數據索引按月創建生成, 業務查詢時候必須帶上操作時間范圍,后端根據時間反推需要查詢哪些索引,Elastic-Api支持多索引匹配查詢,完美利用Elastic的特性解決跨多個月份的查詢合并。對于非核心數據索引,按年創建索引生成足以。
圖示:Elastic操作日志索引創建規則
3、核心實現邏輯設計
Elasticsearch不是關系型數據庫,不具備事務的機制。操作日志系統的數據來源都是Kafka,消費數據是有順序機制的,有2種場景特別注意,如下:
主數據先到操作日志系統,從數據后到,從數據寫的時候先拼湊主數據記錄和Binlog字段數據;
從數據先到操作日志系統,主數據后到,主數據更新從索引的相關的索引字段。
Elasticsearch索引數據更新是近實時的刷新機制,數據提交后不能馬上通過Search-Api查詢到,主記錄的數據如何更新到從記錄呢?而且業務部門不規范的使用,多條主記錄的dataId和tracId可能一樣。
由于主數據與從數據關聯字段是dataId和traceId。如果主數據與從數據在同時達到操作日志系統,基于update_by_query 命令肯定失效不 準確, 主從數據也可能是多對多的關聯關系,dataId 和traceId不能唯一決定一條記錄。
Elasticsearch其實也是一個NoSQL數據庫, 可以做key-value緩存。這時新建一個Elastic索引作為中間緩存, 原則是主數據與從數據誰先到緩存誰,索引的 _id=(dataId+traceId) , 通過這個中間索引可以找到主數據記錄的Id或者從記錄Id, 索引數據模型多如下,detailId為從索引的_id的數組記錄。
{ "dataId": 1, "traceId": "abc", "moduleCode": "crm_01", "operationId": 100, "operationName": "張三", "departmentId": 1000, "departmentName": "客戶部", "operationContent": "拜訪客戶", "detailId": [ 1, 2, 3, 4, 5, 6 ] }
前面我們講過主記錄和從記錄都是一個Kafka的分區上,我們拉一批數據的時候,操作ES用的用到的核心API:
#批量獲取從索引的記錄 _mget #批量插入 bulk #批量刪除中間臨時索引 _delete_by_query
遷移過程
1、數據遷移
選擇DataX作為數據同步工具由以下幾個因素:
歷史型數據。操作日志記錄數據屬于歷史性的數據,記錄產生之后幾乎無需二次修改,等同于離線數據;
非持續性遷移。項目全部完工之后,原有的MongoDB集群會全部銷毀,不會有二次遷移需求;
數據量問題。原有MongoDB操作日志數據量有幾十億條,遷移過程不能太快也不能太慢,速度太快,MongoDB集群會出現性能問題,速度太慢,項目周期太長,增加運維的成本與復雜度。否則可以選擇Hadoop作為中轉平臺的遷移;
DataX源碼特定場景改造。如日期類型的轉換、索引主鍵_id的生成、索引主鍵_id映射,支持重復同步;
多實例多線程并行。主數據同步部署多個實例,從數據同步也部署多個實例,單實例中配置多個Channel。
圖示:DataX同步數據示意圖
2、遷移索引設置
臨時修改索引的一些設置,當數據同步完之后再修改回來,如下:
"index.number_of_replicas": 0, "index.refresh_interval": "30s", "index.translog.flush_threshold_size": "1024M" "index.translog.durability": "async", "index.translog.sync_interval": "5s"
3、應用遷移
操作日志項目采用Springboot構建,增加了自定義配置項,如下:
#應用寫入mongodb標識 writeflag.mongodb: true #應用寫入elasticsearch標識 writeflag.elasticsearch: true
項目改造說明:
第一次上線的時候,先將2個寫入標識設置為true,雙寫MongoDB和ES;
對于讀,提供2個不同接口,前端自由的切換;
等數據遷移完,沒有差異的時候,重新更改flag的值。
圖示:應用平衡遷移
結語
1、遷移效果
棄用MongoDB使用ElasticSearch作為存儲數據庫,服務器從原來的15臺MongoDB,變成了3臺ElasticSearch,每月為公司節約了一大筆費用。同時查詢性能提高了10倍以上,而且更好的支持了各種查詢,得到了業務部門的使用者,運維團隊和領導的一致贊賞。
2、經驗總結
整個項目前后歷經幾個月,多位同事參與,設計、研發,數據遷移、測試、數據驗證、壓測等各個環節。技術方案不是一步到位,中間也踩了很多坑,最終上線了。ES的技術優秀特點很多,靈活的使用,才能發揮最大的威力。
關于棄用MongoDB使用ES后的好處有哪些問題的解答就分享到這里了,希望以上內容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關注億速云行業資訊頻道了解更多相關知識。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。