前言
隨着業務的發展和持續運行,系統會產生大量的數據,數據的增長伴隨而來的是對數據庫的考驗,在達到一定的數據量之后數據庫的訪問性能就會持續下降,為了系統的穩定運行,得要么提高數據庫訪問性能,要么把數據限定在一定的量上。前者會導致IT系統的不斷投入,投入產出比不高,且早晚會達到系統的瓶頸,后者需要拋棄舊的數據,從歷史數據的完整性上來說也是我們不願意看到的。
如果暫時沒有上分析性數據倉庫的需求,那么做冷熱數據的分離就是一個比較好的解決辦法。將熱數據剝離開來,保證熱數據的讀寫性能,冷數據相對來說訪問量少,可以降低服務等級,這樣就減少在IT方面因為數據量增長帶來的投入。如何區分冷/熱數據
我們一般有兩種方式來區分冷熱數據:- 按數據創建時間:一般情況我們會使用數據的創建時間來區分數據冷熱,按常理說越久時間前創建的數據訪問越少,這對於交易類數據很明顯,很可能一周內某筆交易會被頻繁查詢,一個月內也許只是偶爾查詢,三個月后可能在極偶然的情況下才會被用到,有可能絕大多數數據在幾個月后再也不會被訪問到。
- 按訪問熱度:有些數據訪問頻度並非按時間,比如某個熱門文章也許發表一年之后還會有大量的人訪問,新發表的文章反而很少有人瀏覽。或者某個事件會引發某些很少閱讀的文章或者信息在某一個時間段突然大量的被訪問到,這樣冷數據也會變成熱數據。這個時候再按時間區分就不科學了,需要按業務情況、數據規律來區分冷熱。
冷數據的特點
- 數據量大:冷數據要求保存較長時間甚至所有時間的,這可能是熱數據的數十倍到數百倍的數據量。
- 業務場景簡單:只需要讀取指定的數據即可,一般不會有復雜的查詢。寫入、刪除都會批量處理,基本沒有更新操作。
- 性能要求不高:不像一般應用要求查詢數毫秒到數秒內返回,冷數據的查詢可以容忍數十秒甚至更長時間才出結果,甚至可以做到異步處理,啟動一個任務然后等待結果。
- 成本敏感:因為數據量龐大且訪問頻度低,不適合大量的投入。
冷數據的處理
對於冷數據,根據不同的應用場景建議使用不同的方式來處理。場景一:極低頻度的查詢
通常數據只是備份,但在偶然的情況下需要查詢指定的數據,這種查詢有可能數天到數月才發生一次。
對於這種情況,推薦直接使用oss來存儲冷數據,然后在需要查詢的時候啟動運行一個RDS實例並導入數據,查詢完成后銷毀RDS實例,此方案優點是成本非常低,但在使用的時候會比較繁瑣。
下面以RDS MySQL版為例來說明如何處理。冷數據備份
啟動一個ECS,在其上部署定時任務,任務步驟包括:- 使用mysqldump命令導出指定時間段的數據:mysqldump -h hostname -u username -p password tablename > dbname-tablename-年月日時分秒.sql –where querystatement
- 打包上傳備份數據到oss
- 備份完成后刪除RDS中已備份的數據(注意非drop或者truncate命令刪除的數據,可能需要定期執行optimize table命令來釋放空間)
使用冷數據
- 啟動一個RDS按量實例
- 登錄ECS,從oss下載指定時間的備份包
- 執行數據恢復命令,如:mysqldump -h hostname -u username -p password -h host tablename < xxx.sql
- 登錄控制台DMS或者MySQL客戶端,查詢數據
- 釋放MySQL實例
場景二:需要經常查詢
冷數據經常被查詢,比如每天不同時間段都有人在查詢數據,這個時候如果每次查詢都重復啟動數據庫或者導入數據的操作就太過繁瑣,此時建議以下兩個方案備選(下面也都以RDS MySQL版為主數據庫來做示例)。方案一:冷熱RDS
建立冷/熱數據庫,熱庫僅保留短時間的數據,超出的數據定時批量移到冷庫中。應用系統內部做好區分,熱數據可以直接通過應用系統訪問,如果需要訪問冷數據則需要走冷庫查詢。
熱庫面對大量的高頻查詢寫入請求,因此配置高規格的RDS,冷庫的數據查詢頻率一般非常低,可以配置低規格的RDS並提供大存儲容量。例如對某種應用熱RDS使用8核16G內存200G磁盤空間的話,那么根據冷數據訪問的頻度和性能要求,冷RDS可以用1核2G、2核4G內存等低規格的實例,並提供最大到2T的存儲空間。
冷熱RDS方式部署簡單,但數據庫存儲在RDS的內部存儲上,成本還是相對比較高。另外單個RDS還是有磁盤空間上限的限制,最高只能到2T。如果想要降低成本或者需要更高的存儲空間,除了采用分布式數據庫外(分布式數據庫成本也會比較高),可以考慮用以下另一種方式。方案二:冷數據轉存RDS PostgreSQL版 + OSS
冷數據從RDS MySQL版轉存到RDS PostgreSQL版上,並用oss_ext擴展插件把數據以外部表的方式存入oss,使用oss的低廉成本和無限空間的特性來存儲大量的冷數據,並且可以通過PostgreSQL直接查詢。准備工作
- 創建RDS PostgreSQL版實例,選擇合適的實例規格
- 創建oss插件:create extension oss_fdw;
- 創建 server :create server ossserver foreign data wrapper oss_fdw options (host 'oss-cn-hangzhou.aliyuncs.com' , id 'xxx', key 'xxx',bucket 'mybucket');
- 在PostgreSQL中創建數據表(數據列是示例):create table example (date text, time text, open float, high float, low float, volume int);
轉儲冷數據
運行一個ECS,在上面部署定時任務,任務包括以下內容:
- 導出數據到csv文件中:mysql -B -u username -p password database -h dbhost -e "SELECT * FROM xxxtable;" \ | sed "s/'/\'/;s/\t/\",\"/g;s/^/\"/;s/$/\"/;s/\n//g" > example.csv
- 上傳csv文件到oss中
- (此步驟也可以在查詢時候做)在PostgreSQL中創建oss外部表:CREATE FOREIGN TABLE oss-data-xxx (date text, time text, open float,high float, low float, volume int) SERVER ossserver OPTIONS ( filepath 'osstest/example.csv', delimiter ',' ,format 'csv', encoding 'utf8', PARSE_ERRORS '100');
- 刪除RDS中數據(注意非drop或者truncate命令刪除的數據,可能需要定期執行optimize table命令來釋放空間)
查詢冷數據
- 裝載外部表中數據到數據表:insert into example select * from ossdata-xxx;
- 查詢數據表
- 查詢完后清除數據表中數據(PostgreSQL實例本身存儲容量有限),預留空間給其他查詢使用