将数据(递增地)加载到Amazon Redshift,S3与DynamoDB vs Insert中

时间:2014-01-11 23:12:31

标签: amazon-web-services amazon-s3 amazon-ec2 amazon-dynamodb amazon-redshift

我有一个需要发送其使用情况报告的网络应用程序,我想将Amazon RedShift用作数据仓库, 我该如何收集数据?

每次,用户与我的应用程序进行交互,我想报告..所以我应该何时将文件写入S3?多少钱? 我的意思是:   - 如果不立即发送信息,那么我可能会因为连接丢失而失去它,或者我的系统中的一些错误被收集并准备好发送到S3 ...   - 如果我在每次用户交互时都将文件写入S3,我最终会得到数百个文件(每个文件都有最少的数据),需要在复制到RedShift后进行管理,排序,删除......喜欢一个好的解决方案。

我缺少什么?我是否应该使用DynamoDB,我应该使用简单的插入Redshift!? 如果我确实需要将数据写入DynamoDB,我应该在复制后删除保留表吗?最佳做法是什么?

在任何情况下,在RedShift中避免数据重复的最佳做法是什么?

感谢帮助!

5 个答案:

答案 0 :(得分:44)

首选聚合事件日志,然后再将其导入Amazon Redshift。

好处是:

  • 您将更好地使用Redshift的并行特性;对于S3(或大型DynamoDB表)中的一组较大文件,COPY将比单个INSERT或小文件的COPY快

  • 在将数据加载到Redshift之前,您可以预先排序您的数据(特别是如果排序基于事件时间)。这也可以提高您的负载性能并减少对VACUUM表的需求。

您可以在聚合并将其加载到Redshift中之前在多个地方累积您的活动:

  • 本地文件到S3 - 最常见的方法是在客户端/服务器上聚合日志,每x MB或y分钟将它们上传到S3。有许多日志追加器支持此功能,您无需在代码中进行任何修改(例如,FluentDLog4J)。这可以仅使用容器配置来完成。不利的一面是,您可能会丢失一些日志,并且可以在上传之前删除这些本地日志文件。

  • DynamoDB - 正如@Swami所描述的,DynamoDB是一种积累事件的好方法。

  • Amazon Kinesis - 最近发布的服务也是一种很好的方式,可以快速可靠地将您的活动从各种客户端和服务器流式传输到中心位置。事件按插入顺序排列,这样可以在以后预先排序到Redshift时轻松加载它。事件存储在Kinesis中24小时,您可以安排从kinesis读取并每小时加载到Redshift,例如,以获得更好的性能。

请注意,所有这些服务( S3,SQS,DynamoDB和Kinesis )都允许您直接从最终用户/设备推送活动,而无需通过中间Web服务器。这可以显着提高服务的高可用性(如何处理增加的负载或服务器故障)和系统成本(您只需支付使用的费用,而不需要仅为日志使用未充分利用的服务器)。 / p>

例如,请参阅此处了解如何为移动设备获取临时安全令牌:http://aws.amazon.com/articles/4611615499399490

允许与这些服务直接交互的另一组重要工具是各种SDK。例如Java.NETJavaScriptiOSAndroid

关于重复数据删除要求;在上面的大多数选项中,您可以在聚合阶段执行此操作,例如,当您从Kinesis流中读取时,您可以检查事件中是否没有重复,但在放入之前分析大量事件缓冲区进入数据存储区。

但是,您也可以在Redshift中进行此检查。一个好的做法是将COPY数据导入临时表,然后SELECT INTO组织良好的排序表。

您可以实现的另一个最佳实践是每日(或每周)表分区。即使您想要一个大的长事件表,但大多数查询都在一天(例如最后一天)运行,您可以创建一组具有类似结构的表(events_01012014,events_01022014,events_01032014 ...)。然后,您可以SELECT INTO ... WHERE date = ...到每个表。如果要查询多天的数据,可以使用UNION_ALL

答案 1 :(得分:6)

要考虑的一个选项是在DynamoDB中创建时间序列表,您可以在DynamoDB中每天或每周创建一个表来编写每个用户交互。在时间段(日,小时或周)结束时,您可以将日志复制到Redshift。

有关详细信息,请参阅DynamoDB时间序列表,请参阅此模式:http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GuidelinesForTables.html#GuidelinesForTables.TimeSeriesDataAccessPatterns

和这个博客:

http://aws.typepad.com/aws/2012/09/optimizing-provisioned-throughput-in-amazon-dynamodb.html

对于Redshift DynamoDB副本:http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/RedshiftforDynamoDB.html

希望这有帮助。

答案 2 :(得分:2)

尽管此处已有一个已接受的答案,但AWS推出了一项名为Kinesis Firehose的新服务,该服务根据用户定义的时间间隔处理聚合,临时上传到s3,上传(SAVE)到红移,重试和错误处理,吞吐量管理等......

这可能是最简单,最可靠的方法。

答案 3 :(得分:2)

您可以将数据写入本地磁盘上的CSV文件,然后运行Python / boto / psycopg2脚本以将数据加载到Amazon Redshift。

在我的CSV_Loader_For_Redshift我这样做:

  1. 使用boto Python模块和分段上传,将数据压缩并加载到S3。

    conn = boto.connect_s3(AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY)
    bucket = conn.get_bucket(bucket_name)
    k = Key(bucket)
    k.key = s3_key_name
    k.set_contents_from_file(file_handle, cb=progress, num_cb=20, 
    reduced_redundancy=use_rr )
    
  2. 使用psycopg2 COPY命令将数据附加到Redshift表。

    sql="""
    copy %s from '%s' 
    CREDENTIALS 'aws_access_key_id=%s;aws_secret_access_key=%s' 
    DELIMITER '%s' 
    FORMAT CSV %s 
    %s 
    %s 
    %s;""" % (opt.to_table, fn, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY,opt.delim,quote,gzip, timeformat, ignoreheader)
    

答案 4 :(得分:1)

在这里做一点自私,并准确描述事件分析平台的Snowplow。他们使用这种非常独特的方式从客户端收集事件日志并在S3上聚合它。

他们使用Cloudfront进行此操作。您可以做的是,在其中一个S3存储桶中托管一个像素,并将该存储桶放在CloudFront分配后面作为原点。为同一个CloudFront启用日志到S3存储桶。

每当您在客户端上调用该像素时,您都可以将日志作为网址参数发送(类似于Google Analytics)。然后可以使用“复制”来丰富这些日志并将其添加到Redshift数据库中。

这解决了日志聚合的目的。此设置将为您处理所有这些。

您还可以查看Piwik这是一个开源分析服务,看看您是否可以根据需要对其进行修改。