前言
随着业务的发展和持续运行,系统会产生大量的数据,数据的增长伴随而来的是对数据库的考验,在达到一定的数据量之后数据库的访问性能就会持续下降,为了系统的稳定运行,得要么提高数据库访问性能,要么把数据限定在一定的量上。前者会导致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实例本身存储容量有限),预留空间给其他查询使用
总结
本文提供了三种冷热数据分离的方案,可以根据应用系统的特征和需求选取其中一种,也可以对系统中的不同数据使用不同的方案,甚至对于不同时间段的同样数据使用多种方案,比如短期的冷数据可能还会有一定的访问,可以使用冷热RDS方式,长期基本不怎么访问的冷数据直接导出放到oss上,可以进一步提高灵活性和降低使用成本。
<<完>>