驚了! MySQL 熱冷數據分離設計還能這樣!

2021-02-19 民工哥技術之路
資料庫發展簡介

數據量的增長其實一直是隨著網際網路的發展呈現爆發式增長的,因為各種各樣的數據都在不斷的被原樣或者是經過少量的更改和增補後拷貝到網際網路的各個角落。為了適應網際網路數據的海量增長,在後端和架構意義上而言,資料庫的發展也大致經歷了「單庫單表 -> 主從讀寫分離 -> 分表分庫 -> NoSQL -> NewSQL」這樣的過程。

一開始,我們把數據都堆在一個數據表裡;後來為了提高性能、增加數據擴展的能力,採用了「主從讀寫分離」和「分表分庫」的方式,前者只需要在主從實例之間做數據同步而不會對既有業務有較大的影響,後者則需要用一套切合業務邏輯的方式合理的制定分表分庫的策略;再後來出現的 NoSQL,打破了傳統關係型資料庫固有的一些限制,它們有不同的類型,有的是為了解決高性能讀寫的需求,有的則是為了解決海量數據存儲的需求,還有的需要數據結構本身具備可擴展性;

NoSQL 的不同類型在不同的側重點解決了不同的問題,而如今出現的 NewSQL 則傾向於把資料庫看作是一個黑匣子服務,你還是可以遵照傳統的資料庫協議的使用方式(比如傳統 MySQL 的使用方式)來使用它,但數據存儲服務本身既可以同時具備較高的讀寫性能又可以輕易的實現橫向擴展。NewSQL 並不是一個全新的東西,我們可以把它看作是之前積累的資料庫技術結合分布式技術的集大成解決方案,它使得使用數據服務的人幾乎不需要再考慮性能和擴展問題,而儘量在數據服務內部實現高可用、高性能、可擴展。

「熱數據」和「冷數據」

在簡單了解了資料庫發展歷程之後,再介紹一下我們目前在數據存儲上遇到的問題和一些業務背景。

作為氣象大數據服務商,隨著我們積累的數據量和數據種類越來越多,我們發現我們已經迫切需要一個在全局層面統一的數據路徑規劃和規範。很多時候,我們從數據源獲取到的數據,既需要馬上分發給線上用戶,也需要被內部項目使用,如果只是簡單的按需實現,那數據流轉會非常混亂。基於這種考慮,我們引入了「熱數據」(「在線數據」)和「冷數據」(「離線數據」)的概念:

「熱數據」指的是需要即時對用戶進行分發的數據,即從數據源抓取之後經過數據清洗,需要即時存儲到可以快速分發的存儲介質(如 Redis)供 API 或直接面向用戶的系統使用。「熱數據」線需要重點保障服務質量和穩定性,為了保證數據的時效性,在數據處理上也是優先級高的數據。「熱數據」可能是臨時或短期存儲的,後來的數據可能會覆蓋已有的數據。

「冷數據」指的是不需要即時分發給用戶的數據,這些數據甚至可能永遠都不會原樣分發給用戶的,但它們需要經過長期的積累,使我們可以從中得出基於此的更高 level 的分析。「冷數據」典型的使用場景是供內部數據評估系統做數據準確度的評估分析,同時也可以給算法團隊建模使用。設立這個數據線的原則是不影響「熱數據」的服務質量,尤其是時效性和穩定性,同時也滿足一些非線上項目的數據使用需求。

這其實也不是什麼新鮮的概念,很多做數據服務的公司都有類似的設計,我們只是根據我們的業務特點借用了這樣的概念,不過它們的含義可能與你在其他地方看到的類似概念的含義有所不同。

結合我們具體的業務場景來說,「熱數據」線其實已經一直在有效運轉了,即我們從數據源獲取到數據然後儘快存儲到高性能存儲介質中,再通過HTTP協議分發出去,這些數據都是即時更新的最新的數據。而其中有一些類型的數據,我們還需要在可視化項目中查看歷史變化情況,並能進行簡單的聚合和計算,這意味著數據需要積累一段時間,那我們也需要一些可以持久化存儲的介質。

拿天氣實況來舉例,我們在採集完數據之後,隨即就存儲最新的一份數據到Redis,而出於數據積累的角度考慮,我們同時也把新數據寫入MySQL。這是之前我們的做法,然而隨著數據量的極速擴大,問題很快就會出在MySQL上。對於「億」級別行數往上的MySQL單表,操作會變得越來越困難,而大範圍的抽數或者插入數據的操作都可能使得整個MySQL無法提供服務,這對於線上業務而言是不可接受的。

離線數據中心的實現

在提出了「冷數據」的概念之後,我們意識到那些久遠的歷史數據其實需要存放到「冷數據」的數據中心池子裡,而線上MySQL只需要保留最近一段時間的數據即可。另外,為了不改變現有項目使用數據的方式,降低資料庫使用者的門檻,不管是對於線上資料庫還是「離線數據」的數據中心,我們都需要兼容MySQL單表的使用協議。

很快我們就開始考慮NewSQL的方案,TiDB很自然地進入了我們的視野,這是一個既可以兼容現有數據使用方式,又可以實現數據橫向擴展的完美方案,但無奈搭建一個最小版本的TiDB 數據集群的成本,相比於目前我們把它作為一個「離線數據」存儲中心的角色而言,還是有一些偏高,而我們的存量服務也基本都是基於阿里雲的,所以最終我們選擇了阿里雲推出不久的雲資料庫PolarDB。其間我們還研究了很多其他資料庫方案,比如DRDS、OceanBase、Google Cloud Spanner、Amazon Aurora等。

數據同步和數據過期

有了離線數據存儲中心之後,我們開始考慮如何把「熱數據」轉化為「冷數據」,同時也使得線上資料庫可以自動過期超出時間窗口的歷史數據。另外,由於內部可視化項目也希望看到實時的實況數據,所以離線數據最好也能很快獲得最新的實況數據。

既然是兩個 MySQL(集群)之間的實時數據轉移,很自然的就想到了我們可以做類似主從節點之間通過 binlog 的數據同步機制,這個同步可以做到秒級延遲,在實時性上是完全可以接受的。不過這不能是簡單的數據同步,因為離線數據是不能同步線上數據的過期操作的。更具體的,我們可以概括成:MySQL 從節點同步主節點所有數據增添和數據修改的操作,而對於數據的刪除操作不做同步。

在調研之後,我們發現TiDB提供的同步工具Syncer可以實現這一點,我們只需要在配置註明過濾掉DELETE的DML語句即可,示例如下:

[[skip-dmls]]
db-name = "weather_data"
tbl-name = "weather_now_history"
type = "delete"

而數據過期方案則可以直接藉助MySQL本身的EVENT和PROCEDURE機制完成。首先我們可以創建一個刪除數據的PROCEDURE:

CREATE DEFINER=`weather`@`%` PROCEDURE `weather_data`.`del_old_data`(IN `date_inter` int)
BEGIN
  delete from weather_data.weather_now_history where datetime < date_sub(curdate(), interval date_inter day);
END

這個PROCEDURE功能是刪除weather_now_history表中date_inter天之前的數據。然後我們再創建一個EVENT:

CREATE EVENT del_old_data
ON SCHEDULE EVERY 1 DAY
STARTS '2018-12-25 10:08:35.000'
ON COMPLETION PRESERVE
ENABLE
DO call del_old_data(30)

這個EVENT則會每天調用一次名為del_old_data的PROCEDURE,並同時把date_inter 賦值為30。這意味資料庫每天會刪一次數據,使得線上資料庫一直只保留最近30天的數據,而全量的數據是在數據寫入時就實時同步到了離線數據中心,可謂完美。

持續改進

上述的具體業務場景更多的還是case by case的解決了「熱數據」和「冷數據」的分離和轉化問題,這意味著方案並不具有普適性,以後我們遇到其他的資料庫或者不同的數據使用場景可能就不再適用。

另外,很多時候,「熱數據」和「冷數據」的劃分並不是那麼明晰的,對於「冷數據」的需求有可能轉變為「熱數據」需求,我們需要可以靈活切換的機制,做到數據源只抓取一次(「熱數據」和「冷數據」不要分別抓取),而抓取到的數據可以任意自由的流淌到「熱數據」或「冷數據」線使用,這意味著我們在數據抓取和數據存儲之間應該再做一層隔離。

要實現數據抓取和數據存儲之間的隔離,我們可以採用「發布 / 訂閱模式」:簡單說,數據抓取服務在獲取數據之後將數據發布到消息隊列,後面的存儲服務任意訂閱這個消息隊列再做存儲,這樣數據源只需要抓取一次,我們可以把它作為熱數據使用,也可以作為冷數據使用,甚至可以即作為熱數據又作為冷數據使用,切換起來也十分簡單。這是後續系統架構可以改進的一個地方。

另外,離線數據中心僅僅使用 PolarDB 對於我們可能產生的數據量級而言也是遠遠不夠的,我們還需要更低成本的數據存儲方案來存儲時間更久遠、平時幾乎不大會訪問的一些需要被「歸檔」的數據,這個時候,一些基於列存儲的 NoSQL 資料庫可能可以派上用場。

數據治理需要一個長期持續的過程,我們還在結合自身的業務場景不斷的摸索當中。

來源:http://maples7.com/2018/12/25/hot-cold-data-based-on-mysql/

相關焦點

  • Mysql數據誤刪除快速回滾
    作者 | Video++極鏈科技OPSTeam整理 | 包包在資料庫操作中,難免會因為各種各樣的原因對數據造成損壞,這個時候就需要對資料庫快速恢復。傳統的方法會先恢復mysql備份,再去用mysqlbinlog抽取指定時間點的日誌,再恢復,這樣的操作比較耗時,容易出錯,那有沒有一種工具可以快速把誤刪除的操作SQL逆過來,然後重新插入誤刪除的數據呢?binlog2sql,就是一個很好的應用,它可以從MySQL binlog解析出SQL,根據不同選項,你可以得到原始SQL、回滾SQL、去除主鍵的INSERT SQL等。
  • 電子數據取證之MySQL資料庫刪除數據的恢復指南
    binlog日誌包括兩類文件:1)二進位日誌索引文件(文件名後綴為.index):用於記錄所有的二進位文件;2)二進位日誌文件(文件名後綴為.00000*):記錄資料庫所有的DDL和DML(除了數據查詢語句select)語句事件。binlog日誌對於mysql資料庫來說是十分重要的。在數據丟失的緊急情況下,可以嘗試用binlog日誌功能進行數據恢復操作。
  • MySQL性能優化
    Mysql資料庫的優化技術對MySQL優化是一個綜合性的技術,主要包括表的設計合理化(符合3NF)添加適當索引(index) [四種: 普通索引、主鍵索引、唯一索引unique、全文索引]分表技術(水平分割、垂直分割)讀寫[寫: update/delete/add]分離存儲過程 [模塊化編程
  • mysql指令、數據類型、表結構、約束學習記錄
    mysql常用口令--修改用戶密碼的命令mysqladmin -uroot -proot123 password mysql123--登錄mysql資料庫的命令mysql -uroot-proot123--顯示資料庫的命令show databases;--使用資料庫的命令use mysql;--顯示當前連接的資料庫select database
  • MySQL基於MHA的FailOver過程
    ping檢查資料庫狀態,主機狀態,埠等,判斷從庫節點讀取的master_log_file及read_master_log_pos節點大小,查看Retrieved_gtid_set(已接收到的gtid大小),executed_gtid_set(已執行的gtid號大小)3.數據補償
  • Mysql自增id用完了,到底會不會報錯?
    前些天有個粉絲在群裡發了一張圖片,成功引起了我的注意,圖片如下:大致內容是在mysql中,一個表的自增id用完了,繼續插入到底會不會報錯?說實話,工作這麼多年,我還真沒遇到這種問題,也沒太想過,我的第一反應應該是會報錯,否則mysql也不會有那麼多類型和長度的限制;但是同時我也很疑惑,說不定mysql有什麼保護機制,可以自動升級類型之類的,接下來我將帶領大家去一層層揭開這個疑點。我們可以想一下,資料庫為什麼需要主鍵?不需要主鍵行不行?
  • 如何應用策略設計模式分離JDBC資料庫連接中的外部環境信息
    軟體項目實訓及課程設計指導——如何應用策略設計模式分離JDBC資料庫連接中的外部環境信息1、什麼是策略(Strategy)設計模式策略設計模式把「算法」(也就是軟體應用系統中的業務規則或者待實現的功能等)和「環境」(封裝軟體應用系統在實際應用時的場景)相互分離
  • 技術分享 | MySQL:timestamp 時區轉換導致 CPU %sy 高的問題
    timestamp:佔用 4 字節,內部實現是新紀元時間(1970-01-01 00:00:00)以來的秒,那麼這種格式在展示給用戶的時候就需要做必要的時區轉換才能得到正確數據。下面我們通過訪問 ibd 文件來查看一下內部表示方法,使用到了我的兩個工具 innodb 和 bcview。詳細參考:https://www.jianshu.com/p/719f1bbb21e8。
  • 免安裝版MySQL操作步驟
    1、 修改mysql安裝目錄下的my.ini文件a) 將Mysql的壓縮包先解壓,解壓後mysql安裝目錄下有如下的文件和文件夾:b) 打開my.ini文件(可以用記事本打開)>a) 將mysql安裝目錄中的bin文件夾的目錄,寫入系統變量path中3、 將mysql設置為服務a) 使用管理員權限進入dos命令窗口i. 「 如何以管理員身份進入dos命令窗口?
  • 在mysql中如何刪除記錄?delete關鍵字了解一下
    在上一篇文章中我們學習了如何更新mysql中的數據內容,用到的是update這個關鍵字,今天我們要學習的是如何讓在mysql中刪除記錄,也就是從箱子裡面拿走東西,用到的關鍵字是delete這個關鍵字,下面我們就通過一個例子來了解一下。
  • 數據中心「冷」戰:風冷「不冷」液冷崛起
    風冷數據中心非常突出的一個短板:機架的功率密度偏低,遠遠達不到超大規模數據中心和高性能計算中心30kw+的需求。數據中心空間寸土寸金,風冷「不冷」的矛盾日益突出。作為風冷技術的升級方案,液冷技術快速崛起,已經成為大勢所趨。
  • MySQL怎麼刪除#sql開頭的臨時表
    處理方法3.1   同時存在.frm 和.ibd名稱相同的文件如果 #sql-*.ibd 和 #sql-*.frm兩個文件都存在數據目錄裡的話,可以直接drop table。但注意刪除時候表名的變化。/* 直接刪除,表名前加#mysql50*/root@testdb 01:42:57> DROP TABLE `#mysql50##sql-ib87-856498050`;註: #mysql50#前綴是MySQL 5. 1 中引入的文件名安全編碼。另外,表名因不符合命名規範,想要執行該腳本需要將表名用反引號括起來。
  • MySQL如何計算統計redo log大小
    MySQL沒有像Oracle中那樣的系統視圖統計這些數據,但是我們可以通過一些方法曲線的統計二進位日誌的生成量。有具體數據支撐,你才好分析判斷,否則巧婦也難為無米之炊。USE mysqls;CREATETABLEIFNOTEXISTS innodb_log_size_his( log_id INT AUTO_INCREMENT PRIMARYKEY COMMENT '日誌編號', log_date DATETIME COMMENT '記錄當前數據的時間', log_size
  • ProxySQL之讀寫分離與分庫路由演示
    目前在六度人和科技任MySQL DBA,先後兩次主導資料庫整體遷移,幫助開發優化了大量SQL、提供結構設計建議,並組織培訓。工作平時在工作中遇到的一些問題和處理經驗,有空會寫寫放在個人博客上 http://seanlook.com ,也會在裡面分享一些Python寫的工具。
  • 小心避坑:MySQL分頁時使用 limit+order by 會出現數據重複問題
    1、問題描述在MySQL中我們通常會採用limit來進行翻頁查詢,比如limit(0,10)表示列出第一頁的10條數據,limit(10,10)表示列出第二頁。但是,當limit遇到order by的時候,可能會出現翻到第二頁的時候,竟然又出現了第一頁的記錄。
  • Python連接MySQL資料庫方法介紹(超詳細!手把手項目案例操作)
    作者 | CDA數據分析師 來源 | CDA數據分析研究院本文涉及到的開發環境:作業系統 Windows 10資料庫 MySQL 8.0Python 3.7.2pip 19.0.3兩種方法進行資料庫的連接分別是PyMySQL和mysql.connector步驟:連接資料庫生成遊標對象執行SQL語句關閉遊標關閉連接PyMySQL
  • MySQL 8.0.22正式發布
    SQL語法:支持對YEAR數據類型進行轉換,支持TIMESTAMP使用UTC,並且支持通過JSON_VALUE()返回JSON值。功能和函數方面:使用MySQL伺服器的新的異步連接故障轉移機制,在從副本到源的現有連接失敗後,自動建立到新源的異步(源到副本)複製連接。
  • MySQL中order by與limit不要一起用!
    摘自「LIMIT 查詢優化」如果你只需要結果集中的指定數量的行,那麼請在查詢中使用 LIMIT 子句,而不是抓取整個結果集並丟棄剩下那些你不要的數據。這樣這樣的話可以避免抓取全部結果集,然後再丟棄那些你不要的行。對於 order by 查詢,帶或者不帶 limit 可能返回行的順序是不一樣的。如果 limit row_count 與 order by 一起使用,那麼在找到第一個 row_count 就停止排序,直接返回。
  • 圖解MySQL索引——B-Tree(B+Tree)
    非聚簇索引:不是聚簇索引,就是非聚簇索引四、索引的底層實現mysql默認存儲引擎innodb只顯式支持B-Tree( 從技術上來說是B+Tree)索引,對於頻繁訪問的表,innodb會透明建立自適應hash索引,即在B樹索引基礎上建立hash索引,可以顯著提高查找效率,對於客戶端是透明的
  • springboot+springsecurity實現前後端分離簡單實現!
    通過各種方式學習springsecurity,在B站、騰訊課堂、網易課堂、慕課網沒有springsecurity的前後端分離的教學視頻,那我就去csdn去尋找springsecurity博客,發現幾個問題:要麼就是前後端不分離,要麼就是通過內存方式讀取數據,而不是通過資料庫的方式讀取數據,要麼就是大佬們給的代碼不全、把代碼講的太繞,關鍵部分沒有注釋