如何进行SimpleDB备份



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

SimpleDB速度较慢。每秒可以获得大约4个列表,每个列表包含100条记录。这不是备份大量记录的好方法。

我在网上找到了一些服务,可以为你做备份,但我不愿意给他们我的AWS凭据。

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

我想的一个解决方案是根据Facebook id的最后两位数字创建一个新属性。因此,我会用一个选择"00"、另一个选择为"01"等来启动一个线程,这样可能会运行100个线程,并更快地进行备份(至少在理论上)。一个相关的解决方案是将该域拆分为100个域(这样我就可以单独备份每个域),但这会打破我需要做的一些选择。另一个解决方案,可能更适合PHP,是使用cron作业备份10000条记录并保存"next_token",然后下一个作业从next_toke开始,等等。

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

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

根据我的经验,创建代理碎片属性的方法当然有效。

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

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

这使我们在单个域上的吞吐量比在单个线程上旋转要好。

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

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

  1. 没有"本机"方法可以确保与SimpleDB一致的导出或导入。您有责任理解和管理此w.r.t.应用程序代码的含义
  2. 亚马逊没有提供托管备份解决方案,但许多第三方公司在这一领域提供了一些服务(通常将"备份到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()

相关内容

  • 没有找到相关文章

最新更新