随着 DT 时代的来临,数据对于企业经营决策的价值日益凸显,而企业在进行互联网+转型的过程中,如何让数据架构平滑迁移到大数据平台,对于传统业务的转型升级至关重要。企业 IT 部门该如何进行 PB 级别大数据平台的迁移规划呢,请看云智慧运维总监张克琛带来的经验分享。
提到 PB 级别的大数据解决方案市面上有很多,比较火的有 Hadoop、Spark、Kafka 等等,如果是一个新上线的系统,相信大家都能找到适合自己的方案。但“大数据”在 09 年才逐渐成为互联网信息技术的流行词汇,一个较老的系统如何平滑迁移到 PB 级数据架构呢?
云智慧的第一款产品监控宝是 08 年启动的,在设计之初缓存使用的是 Redis, 数据库使用的是 MySQL,随着业务的高速发展和全球分布式监控点的陆续建立,数据量也从开始的 GB 级迅速发展到 PB 级,大数据成为必然的选择。面对 PB 级别数据存储,云智慧一路走来也踩过很多坑,下面就给大家分享一下监控宝系统架构变迁的几个比较重要的点。
一、Redis 的扩展
我们面临的第一个的问题是 Redis 的扩展,Redis 进程无法使用多核,云智慧监控宝当时的 Redis 进程并发 1.5W,单 core CPU 占用率 95%,偶发会达到 100%,监控宝的任务调度会出现延迟现象,我们做了三套方案:
方案 1:改程序逻辑,基于任务 ID 的一致性 hash 支持 Redis 多实例,但由于研发忙于产品功能,没空修改,此方案只能放弃;
方案 2:Redis Cluster,看到官方架构图,我就直接将此方案放弃了。监控宝有大量的写操作,如果每个点都同步写操作,理论上瓶颈无法解决,不适合我们的使用场景,而且生产环境用这个的好像也不多。
方案 3:Codis, Twemproxy.
最终我们选择了 Codis,目前线上稳定运行一年多,从未出现任何问题。QPS 已经达到每秒 15 万次。整个架构每一层都支持扩展,并且无单点,架构图如下:
Codis 有很多优点,而我们选择的理由如下:
下面是迁移管理图:
而上面这几点 Twemproxy 是不具备的,Codis 唯一的缺点就是稍稍复杂一些,入门的时候稍需要多花些时间,但相比其优点这些都微不足道了。
二、使用 MySQL 处理 PB 级别的数据存储
我们面临的第二个问题是 PB 级别的数据存储,就拿监控宝的网站监控功能来说,云智慧在全球分布有 200+个监测点,这些监测点按用户设置的频率访问指定的网站页面,监测数据传到我们的数据中心。这个服务目前有 30 多万用户在使用,平均数据日增量在 1TB 以上。
这部分数据类似于日志数据,使用 MySQL 来存这些数据并不是什么高大上的做法,如果大家使用过 ELK 的话,会推荐我们使用 elasticsearch 来存储这些日志数据吧。的确是这样,我们的新产品透视宝、压测宝都在用 elasticsearch,也用到了 hadoop、spark、suro、kafka、druid 等大数据相关的框架应用,直接使用文件来存储也是可以的。
但老系统的问题必须要解决。
使用 MySQL 做大量数据存储很容易就想到分库分表,提到分库分表自然就会想到 MySQL 的中间件,大家在网站可以查到一些常用的分库分表的中间件,包括大家比较熟悉的 Atlas、Mycat(cobar)、TDDL 、HEISENBERG、OCEANUS、VITESS、ONEPORXY、DRDS 等,先不谈这些中间件之间的区别,他们共有一个特性,只能在一个维度上对数据进行拆分或者说只能对数据进行一次拆分。
切分数据库分为垂直切分和水平切分,先介绍一个比较简单的垂直切分场景:
有几个数据库在同一个 MySQL 实例中,但因数据库 A 的 IO 相对较高,希望将其单独拉到另外一台服务器上,又不想让研发改动代码。
以前一直以为 Mycat 只能做水平切分,其实也可以垂直切分,很实用,配置也很简单,因各种原因希望将原来一个 MySQL 实例中的多个库分布到多个实例中,直接使用 Mycat 就可以做到,对应用程序来看还是同一个实例,在拆分过程可以通过主从同步实现平滑迁移。
接下来介绍水平切分,水平切分是指将某个表按照某个字段的某种规则来分散到多个表之中,每个表中包含一部分数据。
常用的根据主键或非主键的分片规则:
1、枚举法:
比如数据是按照地区省份来保存的,用户通过多级别划分的,本规则适用于这些特定的场景。
2、求模:
如果分片字段为数字,对分片字段进行十进制/百进制求模运算,数据可以均匀落在各分片内。也见过网友分享的对字符串 hash 取模,支持存在符号字母的字段的分片。
3、范围约定
对分片字段约定一个范围,比如 ID 100001~200000 为一个分片,ID 200001~300000 为一个分片
4、按日期
可以按月,按天,按小时分片
5、一致性 hash
一致性 hash 算法有效解决了分布式数据的扩容问题。这个大家可以查下具体的算法实现。
以上是常用的几种方式,也有一些分片方式是根据上面 5 种变化得来,比如对日期字段 hash 再分片的。
单独使用一种分片规则是很难支撑大量数据的存储,哪怕使用一致性 hash 在生产环境中也是很麻烦的事情,光是数据迁移就是一件让运维头疼的事了,这时候我们需同时采用垂直分片和水平分片,甚至多次水平分片,下面聊一下我们在实际生产中如何使用这些分片规则的。
以监控宝 API 监控为例,先介绍下应用场景,现在我们手机里安装的是各种 APP,其架构中必然存在大量的 API,我们的用户不但要监控单个 API 请求,还要监控连续请求构成的事务, 监控宝 API 监控的正确性是以断言来判断的,每个监测点都会对用户的 API 做出请求,请求数据及断言的结果都将被存储到数据中心。
我们借助于 cobar, 对数据做了两次分片,分片逻辑图如下:
a、 首先我们是通过 cobar ,采用枚举法按监测点 ID 对 DB 这层进行了数据分片,这样做的话物理上同一个监测点的数据在一起,业务上也是好理解的。
b、在程序逻辑中按天对表进行了分片。每天都会有脚本将一月之内的表都创建好。
从上图中大家可以看到,这里扩展上是存在问题的。我们一共有 200 多个监测点,在第一阶段,数据量没有那么大的时候,为了节约成本,我们仅使用了 10 台机器做存储,一台机器存有多个监测点的数据。
随着数据量增大,发展到第二阶段,当某台机器硬盘快存满的时候,我需要将一些监测点的数据迁移至新增进集群的机器中,按这个架构,最多我们可以扩展到 200+台机器。
在生产环境中用户对北上广的监测点是最有兴趣的,所以这些监测点的数据量是最大的。 这样就会发展到第三阶段,部分监测点的数据量大到单台机器的硬盘存不下了。
这时候如何解决问题呢,我们来分析一下数据,单个数据库中是按日期来分表的,而大于 3 个月的历史数据较少有人查询,用户也可以接受历史数据查询时间稍长一些,于是我们选用了 TokuDB 来压缩历史数据,基本上 1T 的数据压缩之后在 100G 左右。1:10 的压缩例,即使这样,理论上最多也只能存储 4P 左右的数据(数据放在 UCLOUD 上,云主机支持的最大硬盘为 2T)。
我们在网站监控的数据分库中解决了这个问题,逻辑图如下,我们从 4 个维度对数据进行了分片
1、按日期为第一维度对数据库分片,必须按日期做第一次分片,并且分片时间点可以在配置文件中自定义。
2、按监测点 ID 为第二维度对数据库分片
3、按实际分片数量对任务 ID 动态取模为第三维度对数据库分片
4、对任务 ID 100 取模为第四维度对数据表分片。
创建后的数据库类名似于 db-201501-monitor01-01、 db-201501-monitor01-02 …… 每个库是有 100 张表。这样可以的好处:
1、冷热数据自然分离
2、可以根据日期无限次分片
3、在同一个时间段里实际分片数可以自定义。理论上可以无限次分片。每次分片服务器的数量是可控的,并且下次分片的时间也变的可预期。可以在最大程度是节约成本。
4、数据无需迁移我
细心的同学会发现这样对数据分片造成一个小问题,我们对任务 ID 做了两次取模,会造成部分实例中的某些表中数据是空的,不过并不影响应用。
以上就是云智慧在过去几年里从传统数据架构向大数据迁移过程中的一些经验,希望为大家的数据架构迁移提供参考。