-
背景
-
廣告系統中,演算法模型預估需要根據廣告的實時轉化統計結果,才能做出更精準的預估;同時,支援多維度聚合查詢(例如按照廣告各個不同層級維度,按照時間不同粒度的維度),並跨大區合併。一開始的版本是基於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
- 支援橫向和縱向擴充套件:縱向使得單機效能更好,橫向支援水平擴充套件
- sql解析:sql預編譯到C++中,這就要求sql語句不要經常變化,好處就是常用的語句少了解析部分,執行會比較快
-
ACID:不是full ACID,A:只對單條語句;I:只支援read commited;D:不是每個事務都持久化。C是目標,AID有缺陷,C也在某種程度下不能完全達到
-
效能:官方有做測評,但被一個facebook的員工吐槽了(https://dom.as/2012/06/26/memsql-rage/,知乎有人對觀點做了總結:https://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分別是:
資料庫/引擎 mysql innodb mysql memory memsql qps 750 10k 50k - 測評過程錄製成youtube視訊:https://youtu.be/zKh8CsgF1OQ
-
但是,這玩意不開源,只有受限制的開發版本(叢集總記憶體不能超過128G)和全功能的商業版本,不開源的情況下,如果使用的不夠普遍,而且對其原理不瞭解的情況下,在生產環境還是不太敢使用。
-
memsql體驗
-
docker映象自帶基準測試,在開10個併發的情況下,寫入qps可以達到140w(當然這個基準測試也是比較水,表欄位只有2個)
-
總結
-
在滿足基本功能的情況下追求效能,memsql確實是不錯的選擇;但是如果對其原理不瞭解的情況下,在生產環境使用,容易踩坑。
-
其他記憶體資料庫
-
VoltDB,也是基於記憶體的關聯式資料庫,也是有收費的商業版和開源版,java寫的,特性待調研。
-
相關資料
-
facebook工程師吐槽memsql:https://dom.as/2012/06/26/memsql-rage/
基於記憶體的關聯式資料庫memsql初探
相關文章
- Aerospike 分散式記憶體資料庫 筆記ROS分散式記憶體資料庫筆記
- 記憶體資料庫記憶體資料庫
- (一) MdbCluster分散式記憶體資料庫——基礎架構介紹分散式記憶體資料庫架構
- 規劃關聯式資料庫學習筆記資料庫筆記
- Mongodb記憶體資料庫MongoDB記憶體資料庫
- Web Sql 關聯式資料庫WebSQL資料庫
- 關聯式資料庫設計資料庫
- 關聯式資料庫之父 (轉)資料庫
- 資料庫新兵:分散式實時分析記憶體資料庫eSight資料庫分散式記憶體
- 關聯式資料庫的封建迷信資料庫
- 關聯式資料庫與文件資料庫對比資料庫
- 關聯式資料庫很快會替代向量資料庫資料庫
- 【記憶體資料庫】TimesTen記憶體資料庫
- 記憶體資料庫如何發揮記憶體優勢?記憶體資料庫
- (二) MdbCluster分散式記憶體資料庫——分散式架構1分散式記憶體資料庫架構
- 關聯式資料庫分片原則資料庫
- Oracle - 資料庫的記憶體結構Oracle資料庫記憶體
- Oracle - 資料庫的記憶體調整Oracle資料庫記憶體
- 關於redis記憶體分析,記憶體優化Redis記憶體優化
- 【大頁記憶體】Oracle資料庫配置大頁記憶體記憶體Oracle資料庫
- 資料庫 - 關聯式資料庫標準語言SQL資料庫SQL
- 從關聯式資料庫遷移到NoSQL雲資料庫資料庫SQL
- 【轉載】關聯式資料庫還是NoSQL資料庫資料庫SQL
- 關於程式的實體記憶體RSS記憶體
- 記憶體管理中關於記憶體每次增長的大小記憶體
- 關於autoreleasepool記憶體管理記憶體
- 關於記憶體錯誤記憶體
- 關於記憶體對齊記憶體
- Python記憶體資料庫/引擎Python記憶體資料庫
- 構建個人記憶體資料庫記憶體資料庫
- 從關聯式資料庫遷移到CouchDB資料庫
- 關於JavaScript的記憶體機制JavaScript記憶體
- 磁碟資料庫與記憶體資料庫的特點比較資料庫記憶體
- 達夢資料庫基礎知識(三)達夢資料庫記憶體結構資料庫記憶體
- Swift列舉關聯值的記憶體探究Swift記憶體
- 瀚高資料庫記憶體結構資料庫記憶體
- 記憶體資料庫發展歷程記憶體資料庫
- 記憶體資料庫快取介紹記憶體資料庫快取