基於記憶體的關係資料庫memsql初探
-
背景
-
廣告系統中,演算法模型預估需要根據廣告的實時轉化統計結果,才能做出更精準的預估;同時,支援多維度聚合查詢(例如按照廣告各個不同層級維度,按照時間不同粒度的維度),並跨大區合併。一開始的版本是基於mysql,但由於統計數據更新太頻繁,非同步定期從mysql撈統計結果,導致mysql經常出現活躍連接數太多而頻頻出現告警。
-
嘗試過很多優化:
-
加數據接入層:中間加一層mysql代理服務data access,快取mysql的統計結果,所有的讀請求都從data access獲取,可以減少mysql的讀壓力(也可以從mysql從庫讀,減少master節點壓力,只是沒去嘗試)
-
減少數據量:刪除歷史的統計數據,只保留業務需要的時間窗口的統計結果
-
減少代理的訪問頻率:即使加了代理(2個節點),但由於mysql需要同步的表數量太多(接近200個),每個表的數據也達到了百萬級別,頻繁訪問也還是會增加mysql的負擔,後面不得已採取犧牲統計的時效性,降低對mysql的訪問頻率
-
加入redis作為統計寫入的快取隊列:前面提到的基本都是針對讀的優化,實時統計的寫入量很大,如果沒有先聚合,拿到一條就寫入一次,一樣會導致mysql負載過高。所以在服務中先聚合後再寫入,但是,由於聚合是在記憶體的,要是服務上線重啟,臨時聚合的數據來不及寫入mysql,又會導致數據丟失。。所以採取了寫入redis的方式,redis作為快取隊列,保存一天內具體到每一分鐘的統計結果,統計程式定期的從redis中撈取結果,再聚合到5分鐘,1個小時,1天,1周的維度。可能這裡有人會問,為什麼不用kafka或者其他主流mq作為快取隊列,由於需要從其他大區把數據撈出來聚合後一起做統計,這個過程可能會由於物理距離原因而超時,導致統計不準,把消費事務設置為 Exactly Once,跨區消費完了後需要發送確認消息,這個延遲比較大。而且,即使能在一次統計中統計正確,但如果前面有其他的統計出現錯誤,會導致當天的統計一直錯下去,沒法補數據。如果用redis,只要數據未過期,可以對之前統計的結果重新統計後覆蓋,雖然會犧牲一點redis的qps,但redis支援的qps能達到15w,本身性能就很好,所以不是什麼大問題。結果就變成了定期的的insert into xx on duplicate xx
-
結果:
-
一系列優化之後,mysql不再告警了,然而,維護的複雜度也變高了,如果需要增加一個維度,redis、data access、上層應用服務都要改一遍,改起來相當麻煩,而且,維度多,也會導致統計的壓力變大。
-
主角出場:這陣子在看《數據密集型應用系統設計》,作者是少有的從工業界干到學術界的牛人,書中提到了基於記憶體的關係資料庫memsql,因此做了簡單的調研。
-
memsql簡介
-
基於記憶體,定期寫磁碟,避免服務重啟後丟數據,類似redis
-
ACID:不是full ACID,A:只對單條語句;I:只支援read commited;D:不是每個事務都持久化。C是目標,AID有缺陷,C也在某種程度下不能達到
-
性能:官方有做測評,但被一個facebook的員工吐槽了(//dom.as/2012/06/26/memsql-rage/,知乎有人對觀點做了總結://zhuanlan.zhihu.com/p/49159963),大概意思就是拿mysql和memsql的不對等的參數做對比,沒有意義。例如:
-
mysql可以設置 innodb_buffer_pool_size大小,如果設置太小,會導致快取命中率變低。
-
mysql設置事務落磁碟的頻率: innodb_flush_log_at_trx_commit,頻率太高也會影響性能
-
最坑的是:由於memsql是以skiplist存的,如果要order by獲取pk最大的元素(定義表是asc),則需要排序,這在mysql中不需要排序。不過,這個問題貌似後來已經修復了(見知乎的評論:)
-
高可用:支援分散式部署
-
有人說,如果把mysql的表的存儲引擎設置為memory,而且設置觸發器寫磁碟,不就可以代替memsql了嗎?於是有人正對innodb、memory、memsql的性能做了測評,請看以下的測評報告。
-
性能測評:
-
直接說結論:在增刪改查都執行的情況下,qps分別是:innodb:750,memory:10k,memsql:50k。如果僅僅是追求性能,犧牲部分ACID特性,還是可以試試。
-
但是,這玩意不開源,只有受限制的開發版本和全功能的商業版本,不開源的情況下,如果使用的不夠普遍,而且對其原理不了解的情況下,在生產環境還是不太敢使用。
-
memsql體驗
-
docker鏡像啟動://github.com/memsql/memsql-docker-quickstart
-
docker鏡像自帶基準測試,在開10個並發的情況下,寫入qps可以達到140w(當然這個基準測試也是比較水,表欄位只有2個)
-
總結
-
在滿足基本功能的情況下追求性能,memsql確實是不錯的選擇;但是如果對其原理不了解的情況下,在生產環境使用,容易踩坑。
-
其他記憶體資料庫
-
VoltDB,特性待調研。
-
相關資料
-
facebook工程師吐槽memsql://dom.as/2012/06/26/memsql-rage/