【问题标题】:How to do a SimpleDB Backup?如何进行 SimpleDB 备份?
【发布时间】:2011-05-31 23:26:10
【问题描述】:

我正在开发一个使用 SimpleDB 存储其数据的 Facebook 应用程序,但我意识到 Amazon 并没有提供备份数据的方法(至少我知道)

而且 SimpleDB 很慢。您每秒可以获得大约 4 个列表,每个列表包含 100 条记录。不是备份大量记录的好方法。

我在网络上找到了一些可以为您提供备份的服务,但我不愿意将我的 AWS 凭证提供给他们。

所以我想使用线程。问题是,如果您对域中的所有键进行选择,则需要等待第一页的 next_token 值才能处理第二页,依此类推。

我为此考虑的一个解决方案是根据 Facebook id 的最后 2 位数字创建一个新属性。所以我会启动一个线程,选择“00”,另一个选择“01”,依此类推,可能有可能运行 100 个线程并更快地进行备份(至少在理论上)。一个相关的解决方案是将该域拆分为 100 个域(这样我可以单独备份每个域),但这会破坏我需要做的一些选择。另一个可能对 PHP 更友好的解决方案是使用 cron 作业来备份假设 10,000 条记录并保存“next_token”,然后下一个作业从 next_token 开始,等等。

有人对此有更好的解决方案吗?如果它是一个 PHP 解决方案,那就太好了,但如果它涉及到其他东西,无论如何都欢迎。

PS:在你提到之前,据我所知,PHP 仍然不是线程安全的。而且我知道除非我在备份期间停止写入,否则会出现一些一致性问题,但在这种特殊情况下我并不太担心。

【问题讨论】:

  • aws.amazon.com/running_databases/#storage_practices AWS 文档说“此外,Amazon SimpleDB 生态系统还开发了许多备份工具,为 Amazon S3 提供简单的域数据备份。”。那是你最好的选择。使用备份工具备份到 S3。然后,您可以将数据从 S3 传输到您喜欢的任何地方。
  • 感谢您的回复,弗兰克!但我似乎在任何亚马逊页面中都找不到这些工具。我发现的唯一工具是第三方工具,它们与亚马逊没有任何关系,所以不确定哪些是安全的,哪些不安全。

标签: php backup amazon-simpledb


【解决方案1】:

根据我的经验,创建代理分片属性的方法确实有效。

或者,我们过去所做的是将备份分解为两步过程,以便尽可能多地获得多处理的潜力(尽管这是在 java 中和写入备份文件我们可以依靠同步来确保写入安全 - 不确定 php 方面的交易是什么)。

基本上,我们有一个线程对域内的数据进行选择,而不是“SELECT * FROM ...”,它只是“SELECT itemName FROM ...”来获取需要的条目的键备份。然后将它们放入项目密钥队列中,线程池使用 getItem API 读取该队列,并以线程安全的方式将其写入备份文件。

这给了我们在单个域上比在单个线程上旋转更好的吞吐量。

但最终,由于我们的夜间备份中有许多域,我们最终恢复为在单线程和“SELECT * FROM 域”类型模型中执行每个域备份,主要是因为我们已经有大量线程在运行,并且线程过载开始成为备份处理器上的一个问题,但也因为备份程序开始变得非常复杂。

【讨论】:

    【解决方案2】:

    截至 2012 年 10 月,我已经研究了这个问题。似乎有三个主要问题支配着选择:

    1. 没有“本机”方式来确保与 SimpleDB 的一致导出或导入。您有责任了解和管理此 w.r.t 的影响。您的应用程序代码。
    2. Amazon 没有提供托管备份解决方案,但许多第三方公司都在这个领域提供了一些东西(通常带有“备份到 S3”作为选项)。
    3. 在某些数据量下,您需要考虑采用多线程方法,这同样具有重要意义:一致性。

    如果您只需要从单个域中转储数据并且您的数据量足够低以至于单线程导出是有意义的,那么这是我编写的一些 Python 代码,它对我来说非常有用。没有明示或暗示的保证,只有在您理解的情况下才使用它:

    #simpledb2json.py
    
    import boto
    import simplejson as json
    
    AWS_KEY = "YOUR_KEY"
    AWS_SECRET = "YOUR_SECRET"
    
    DOMAIN = "YOUR_DOMAIN"
    
    
    def fetch_items(boto_dom, dom_name, offset=None, limit=300):
        offset_predicate = ""
    
        if offset:
            offset_predicate = " and itemName() > '" + offset + "'"
    
        query = "select * from " \
            + "`" + dom_name + "`" \
            + " where itemName() is not null" \
            + offset_predicate \
            + " order by itemName() asc limit " + str(limit)
    
        rs = boto_dom.select(query)
    
        # by default, boto does not include the simpledb 'key' or 'name' in the
        # dict, it is a separate property. so we add it:
        result = []
        for r in rs:
            r['_itemName'] = r.name
            result.append(r)
    
        return result
    
    
    def _main():
        con = boto.connect_sdb(aws_access_key_id=AWS_KEY, aws_secret_access_key=AWS_SECRET)
    
        dom = con.get_domain(DOMAIN)
    
        all_items = []
        offset = None
    
        while True:
            items = fetch_items(dom, DOMAIN, offset=offset)
    
            if not items:
                break
    
            all_items += items
    
            offset = all_items[-1].name
    
        print json.dumps(all_items, sort_keys=True, indent=4)
    
    if __name__ == "__main__":
        _main()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-07-18
      • 2011-08-10
      • 2011-08-16
      相关资源
      最近更新 更多