选择使用亚马逊AWS Redshift做为数据仓库 Redshift的性能和稳定性都还不错

   03/24/2016 11:15 pm   大 中 小 简体 繁體 字体:
1 颗星2 颗星3 颗星4 颗星5 颗星 (点击来评价哦~_~)
    410人参与

在一年多的使用过程中 Redshift 的性能和稳定性都不错, 当然也有一些坑, 这里整理下在使用 redshift 的过程中的一些经验和遇到的问题.

Columnar storage

就是常说的列式存储, 这里只谈应用场景, 理论详情可以看:http://docs.aws.amazon.com/redshift/latest/dg/c_columnar_storage_disk_mem_mgmnt.html

常用的开源数据库 MySQL 和 PostgreSQL 都是传统的行式数据库, 和 columnar storage 在使用场景下都有什么区别呢?

SQL 查询语句一般会分成两种:

  • OLTP (On-line Transaction Processing)
  • OLAP (On-line Analytical Processing)

通常线上业务逻辑就是是常说的 CRUD 都是 OLTP 型 SQL, 对访问速度和并发量的要求很高, 但是 SQL 本身都不会很复杂. 一般也会利用索引来快速定位目标行.

而用来做数据挖掘和 BI 分析的 SQL 一般都是 OLAP 的. 逻辑很复杂, 大量使用 aggregate function 和 window function, 几乎都是查询操作, 要对某一条精确记录进行修改删除的情况很少. 结果需要扫过大量的数据集后进行运算得到.

Columnar storage 适合 OLAP 的场景. 做分析的时候我们只对特定的列感兴趣(这也和我们的表设计有关, 下面会提到), 数据库只会 scan 在 SQL 中指定过的列.

Columnar storage 带来的另一个优势是高压缩比, 可以为每个字段指定不同的压缩算法, 它也提供了方法从当前数据中自动分析出最合适的压缩算法. AWS 在文档中提到他们的客户普遍的压缩比在1: 3 左右, 实际的使用过程中, 我们的数字要高于这个, 最开始使用的时候在1: 7, 最近的的压缩比也在1: 4.8 左右.

一般文件系统的 block size 是 4KB, 而一些用来处理大数据的文件系统会将 block 设置得比较大, 比如 HDFS 是64MB, 而 redshift 是1MB, 在一个 block 中只会存储一个column 的数据, 这样相同类型的数据可以在一个 block 中得到很高的压缩比.

Scalability

Redshift 可以从一个最小 160 GB 的 SSD node 起步,一路扩展到上百 TB. 需要做的也就是在 console 上点几下.

Cluster 会在扩容开始和结束的时候各重启一次, 这时候所有的 DB Connection 会断开. 在扩容过程中 cluster 是 readonly 状态.

但是扩容过程很慢,上次从7节点扩到9节点花了13个小时.

Price

Redshift 现在有四种类型:

aws价格表

使用 reserved instance 的话, 价格可以更省, 详细的价格对比可以看https://aws.amazon.com/redshift/pricing/ , 三年期的合约折扣有75%, 一年期有42%

顺便提下, 使用下面的 SQL 可以查看系统实际的磁盘空间:

 select owner as node, diskno, used, capacity
    from stv_partitions
order by 1, 2, 3, 4;

 

在 2TB node上的输出:

 node | diskno | used  | capacity
  ------+--------+-------+----------
      0  |  0   | 0  |  1906185
      0  |  1   | 0  |  1906185
      0  |  2   | 0  |  1906185

 

2TB 的 HDD node 实际有3块 1861GB 的磁盘, 共 5584.5GB

160GB 的 SSD node 实际给的是两块186GB 的磁盘, 共 372GB

多出来的空间用户不可用, 应该是用来做 replication 的.

Table design

用来做分析的 metrics 数据曾经是存在 MySQL 里的, 分 DB 做了 horizon sharding, 并按天做了 vertical sharding, 使用起来比较麻烦, 只能调用一些固定的 python 函数, 不能直接写 SQL, 更复杂 的分析只能另外写代码, 也没办法和其他的业务表做 join. 并且数据增长非常快, RDS 和 EBS 成本增长很快, 而现在一个月的数据量比迁移前一整年的量都多. 一个 比较复杂的4周 retention 分析, 曾经在 MySQL 上要花半小时(没法直接做, 需要 pull 数据出来再用 python 进行运算), 相同的逻辑现在用纯 SQL 实现,只需要 20s 左右, 这个过程中大概会处理6亿行 左右的数据.

我们以事件的方式定义数据, 比如一个用户注册的事件:

USER_SIGNUP = {
    'source': string,
    'status': string,
    'time': int
}

 

这个事件就有三个字段 source, status, time, 而整个系统中已定义的事件目前接近2000种, 总共有近400个不同的字段定义, 怎么存?

曾经在 MySQL 里的做法是, 只在 table 里定义通用的 str1, str2, int1, int2 这样的字段,然后再定义各个事件的时候把每个 字段的 mapping 也写上, 比如:

USER_SIGNUP = {
    str_1: source,
    str_2: status,
    int_1: time
}

 

问题有:

  • 容易写错, 每个事件的 mapping 是由开发人员各自定义的, 常会出现把 int 写到 string 里去的情况
  • 添加新字段麻烦, 是按天分表的, 有的事件字段特别多,会导致总字段数变多, 但大部分又是空着的, 浪费空间.
  • 数据库中数据不直观,必须用代码做一次 translate 才能查询.

在 redshift 中的做法很简单粗暴, 把400个字段都放一张表里, 然后按月做sharding.

为了对使用者屏蔽 sharding 细节, 会再创建 union view:

create view log_latest_two_month_view as
    select * from logs_2015_01
union all
    select * from logs_2015_02

 

会创建最近2个月,3个月…等等常用时间范围的 view, 使用者可以像在操作一张表一样操作 view, 如果使用者很清楚时间范围,也可以去查特定的表. 这些 view 用 cronjob 在每月的月初刷新.

添加字段的方式, 我现在的做法是将代码中定义的所有字段抽出来, 再从 redshift 的系统表中查出所有的当前字段, 找出两者的 delta, 然后生成相应的 Alter SQL 语句, 批量 patch 到所有的表上去.

distkey & sortkey

设计表的时候 distkey 和 sortkey 需要在一开始就想好, 无法在创建表后更改.

由于 redshift 是一个分布式数据库, 所有的数据自动 distribute 在所有的 nodes 上, 它有三种分布方式, 详见文档:http://docs.aws.amazon.com/redshift/latest/dg/c_choosing_dist_sort.html

我们使用的是按 key 做分布, 所以需要选择一个 distkey, 一般选择最有可能要和其他 table 做 join 的字段, 比如 user_id, 如果同一个用户的数据全部在一个 node 上, 查询过程中就不需要重分发数据, 否则 redshift 会自动迁移数据到一个节点上, 带来额外的网络开销 (用 explain 可以查出 SQL 执行过程中是否发生了数据重分发:http://docs.aws.amazon.com/redshift/latest/dg/t_explain_plan_example.html)

o 亚马逊网络服务AWS更有弹性:

当您的网络应用所需要的资源需求变大时,可以在极短的时间内轻易地扩展变大,满足应用的需求;当您的网络应用所需资源变少时,也可以快速地减少使用的资源,节省费用。

o 亚马逊网络服务AWS更节省成本:

对于初创公司来说,您可以快速的搭建自己的系统在亚马逊云计算平台上,而不用自己去搭建主机或者租用VPS,可以节省您的大量资金,同时加速网络应用的部署和上线速度,抢占市场先机。

1 2 下一页

关键词: , , , , , 

最多人阅读内容