MySQL時間序列存儲引擎的設計與實現
當我們使用MySQL的時候,經常感慨多引擎下數據管理的靈活。不論是innobase這樣帶有ACID特性的數據引擎後端,還是black hole這樣吃掉數據什麼也不做的數據引擎後端,都在不同場合發揮著自己的作用。
享受著各種存儲引擎帶來的便利時,我們也注意到MySQL的存儲引擎開發在國內還是一片藍海。畢竟這種以插件方式載入到MySQL的數據後端,是一個較深涉及到底層的領域,資料庫底層開發在國內也只有一少部分開發者走在這條路上。這不能不說是一個遺憾的事情。
攜程技術保障中心的MySQL時間序列存儲引擎緣起於一次討論,討論的議題是關於哪個時間序列資料庫更適合攜程環境。在這次日常的自由討論中,有人突發奇想的提出,我們是否可以開發一個MySQL的時間序列存儲引擎?沒有已有的時間序列數據部署的繁瑣,沒有那些各具特色的介面調用,不需要熟悉新的系統,還是以SQL的方式來進行數據的訪問。
首先,讓我們看看OpenTSDB是什麼樣的情況。下圖便是OpenTSDB的部署與運行圖示。OpenTSDB的後端存儲是HBASE,需要在各個server上部署信息收集的前端,通過dashboard展示信息。對於現有的時間序列資料庫,每一個都有自己的部署與運行方案。而這些方案並不具備架構上的通用性。
我們所期望的架構是除了底層的存儲組件不同,對於MySQL的用戶來說沒有什麼不同。已有的大部分運維經驗(HA、複製、備份等等)和已有的開發經驗(插入、刪除和更新的操作)都可以繼承自之前的積累,這是任何一個使用MySQL的公司所希望的情況。就如下圖所展示的架構,對於上層用戶來說,感覺不到太多的變化。用戶可以通過標準的SQL編寫自己的應用客戶端來完成數據的採集和展示,提高靈活性。
經過以上的考量,產生了我們的試驗產品,存儲引擎CFL(ctrip fast log),該引擎能夠以快速的日誌方式進行數據的記錄。其完成後就如下圖所示,滿足之前所設想的種種情況。
1、技術介紹
從層次結構來看,MySQL的存儲引擎分為兩個部分。一是實現存儲功能相關的組件,該層提供存儲引擎的具體功能(增刪改查),我們稱之為功能層;一是和MySQL插件介面對接的組件,該層將MySQL的功能調用轉換為存儲引擎的功能調用,我們稱之為介面層。如下圖所示,資料庫的操作(諸如增刪改查等操作)將通過引擎管理層達到存儲引擎的介面層,再由介面層到達功能層。
功能層
功能層是存儲引擎的核心,由於設計目標的不同,存儲引擎的功能層所提供的功能也是不同的。比如innobase引擎的功能層,提供了事務ACID/數據存儲/元信息管理/MVCC等一系列功能,提供完整的資料庫功能;再如CSV存儲引擎,僅提供字元類型的行存儲。這些不同功能的存儲引擎組件,在MySQL的框架下,提供多種多樣的服務。
介紹攜程時間序列存儲引擎的功能層將從兩個主要方面介紹。一是功能層的架構,也就是運行時涉及到的對象和這些對象的作用;一是進行持久化的存儲,該部分將說明在文件層面,數據是如何存儲的。
架構
CFL的架構設計目標是儘可能的提高數據的插入效率,因此並行處理的想法需要貫穿始終。其機製為,不同會話並行的將數據向表對象中插入;表對象通過緩衝區保存插入的數據,當緩衝區寫滿之後,緩衝區加入磁碟寫入隊列,通過專門的寫盤線程並發的寫入磁碟。
下圖為攜程時間序列存儲引擎的架構:
存儲
在設計存儲的時候,根據時序資料庫的特點,首先考慮的是插入的效率,然後是快速的故障恢復。針對插入效率,在設計數據結構時,採用嚴格的順序寫入策略,以此來保證連續插入的效率。這樣不論在傳統硬碟還是在SSD硬碟上,都可以高效的寫入。針對快速故障恢復,通過控制寫入順序(依次寫入數據、索引和控制信息),實現快速的恢復。最後考慮實現上的簡易性,採用索引和數據分別存儲的方式,降低在同一文件中進行存儲管理的控制。
介面層
程序片段
如下代碼片段為介面層部分
MySQL提供的基類handler,存儲引擎需要提供繼承自該類,並實現基類中如ha_open/ha_close等功能函數的類。
繼承handler類的攜程時間序列資料庫的類
介面層架構
該部分將以ha_cfl為例,說明MySQL存儲引擎管理層和引擎介面之間的關係。
操作發送給會話後,會話從引擎管理層獲取到ha_cfl的對象,將操作轉化為對ha_cfl介面的調用,該步驟完成了SQL到存儲引擎介面的對接。
ha_cfl介面接到調用後,將調用轉化為對錶對象的操作,完成handler介面功能到表對象的實現的對接。
2、效果
通過對時間序列數據進行針對性的開發,CFL存儲引擎的插入性能相對於InnoDB和MyISAM引擎有很大的提高。
ips:insert per second
3、總結
由於本次開發為探索性質的開發,時間上或者人力上的限制使產品還不夠完善,不論是設計還是實現上都存在需要改進的地方。如,創建表時對時間戳類型使用和索引列的指定存在限制,導致無法創建多列索引,僅能夠創建時間索引。存儲結構的限制導致刪除和更新無法快速靈活的進行。
但在資源有限的情況下,完成一個概念完整和實現完整的產品。而且正是通過這次探索性開發,打開了MySQL存儲引擎的一扇大門,不論從整體架構到實現細節都有深入研究,積累了很多經驗。攜程技術保障中心DBA團隊希望這些經驗在將來能夠為國內的MySQL社區提供幫助。
【作者簡介】姜宇翔,攜程技術保障中心 高級研究員,具有十多年資料庫領域開發經驗,曾參與國產自主品牌達夢資料庫版本4到版本7開發的全過程,具有豐富的資料庫知識和開發經驗。
加入攜程後,主攻MySQL的源碼研究和改造,在MySQL的存儲引擎/主從複製/審計等領域皆有貢獻,並針對各種特性需求,進行針對性的功能開發。
沒看夠?更多來自攜程技術人的一手乾貨,歡迎搜索關注「攜程技術中心」微信公號哦~
推薦閱讀:
※PHP高並發下的數據同步的解決方法?
※InnoDB存儲引擎MVCC實現原理
※為什麼php在向mysql提交數據時變數外要用單引號?
※MySQL · 性能優化 · MySQL常見SQL錯誤用法
※附近的人怎麼計算出來的?
TAG:MySQL |