V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
DAOCLOUD
推荐学习书目
Python Cookbook
Using Google App Engine
推荐下载
Latest Google App Engine SDK
其他兼容技术
AppScale
darasion
V2EX  ›  Google App Engine

讨论:关于批量清理数据。

  •  
  •   darasion · 2010-12-19 16:02:48 +08:00 · 3884 次点击
    这是一个创建于 4888 天前的主题,其中的信息可能已经有所发展或是发生改变。
    经常遇到这样的事情:
    有很多很多实体,有些实体保存的内容是有效的,有些是无效的。
    现在要将那些无效的实体清理掉。

    我暂时考虑到如下几点:
    1、要判断一个实体是否有效,需要一番计算。
    2、从 datastore 获取实体不能超过一定数量,太多了也会造成麻烦。
    3、考虑到实体有很多,不可能在一次请求中完成有效性判断,会超时。


    所以,要把取实体的工作和判断实体有效性的工作都分成很多次进行。

    ==设想:
    实现的时候,利用 taskqueue 这个东西。

    把任务分成两个 Handler ,一个 FetchHandler 用于从 datastore 取得实体;另一个 CleanUpHandler 于判断每个实体的有效性并完成清理。

    运行的时候,首先调用 FetchHandler ,取得从 datastore 里边取得一定数量的实体,并获得当前 query 的游标(cursor),然后将每个实体 key 作为参数通过 CleanUpHandler 加入 taskqueue ,最后将 cursor 作为参数通过 FetchHandler 加入 taskqueue 。

    这样,通过先加入 taskqueue 的每个 CleanUpHandler 将每个 key 所代表的实体清理完成后,又通过后加入 taskqueue 的 FetchHandler 根据之前提供的 cursor 取得新一批实体并加入 taskqueue,然后再用新的 cursor 作为参数将 FetchHandler 加入 taskqueue。 这样周而复始,直至 cursor 为空。


    ==实测:
    我用 Twitdao 测试了几次,感觉还能用。

    Twitdao 目前大概保存了400多个 access tokens。
    每个 access token 必须通过 urlfetch 调用 twitter api 的 account/verify_credentials 方法根据返回的状态判断有效性。而众所周知 urlfetch 效率是非常低的。

    实际运行发现,FetchHandler 每次取得大约 60 个实体左右的时候,后台 log 有时会出现叹号,说这个请求需要一点优化;FetchHandler 每次取得大约 40-50 个实体的时候,后台 log 的叹号会减少或消失。

    所有 400 多个实体清理完成大约需要几十秒左右(没测,只是后台观察taskqueue的变化),一眨眼就没了,很快。


    ==缺点:
    1、taskqueue 限量很少(好像是10万次调用),如果实体很多很多,太容易超限了。我只测试了几次就用掉了1%。
    2、跟所有递归迭代的东西一样,必须注意那个退出的条件,稍不注意肯定就会无限自我调用而耗尽资源。
    3、CleanUpHandler 只负责清理一个实体,任务有些太轻了,看来需要考虑一次请求清理若干实体才好。
    4、。。。
    5、...
    8 条回复    1970-01-01 08:00:00 +08:00
    julia
        1
    julia  
       2010-12-19 16:58:07 +08:00
    学习
    jeeson
        2
    jeeson  
       2010-12-19 21:27:03 +08:00
    加上时间戳,最后的验证/使用时间,多少时间内的不需要再次验证,这样可以减少验证数量

    否则,如果你的数据够多,短时间内突发访问,对方(twitter)的服务器要遭殃。万一对方来不及5秒-10秒内响应(URLFetch timeout),你的队列会堵塞、重试

    就token数据而言,需要专门验证有效性吗?我觉得使用时发现无效做标志或者清除就好。也可能我没明白
    darasion
        3
    darasion  
    OP
       2010-12-19 22:23:16 +08:00
    @jeeson 如果使用时验证,响应可能会很慢。

    urlfetch 相对别的服务特别慢。比访问datastore数据似乎要慢很多。所以我认为使用时应尽量减少使用时访问 twitter api 的次数。

    另外全世界访问 twitter api 的应用那么多,一定不会在乎我这一个小小的应用,如果真的因为我造成twitter服务器遭殃,那我就太荣幸了。呵呵。

    再说,任务队列是可以通过 queue.yaml 调整执行频度的,GAE限制死了,不必担心什么太多突发请求。每次入队的任务数量也可以通过 FetchHandler 来调整每次取出实体的数量来限制,这样队列中总能保持有限数量的任务而不会冒漾。

    触发批量清理过程,可以设置cron来找个没人访问的时候进行,或者自己手动也可以。
    jeeson
        4
    jeeson  
       2010-12-19 22:38:56 +08:00
    @darasion 我不确定是否理解你的意思

    如果是OAuth,除非用户取消了授权,否则会一直有效。而如果无效,访问的时候,会得到一个401 Unauthorized的错误,把这个token做无效标识就好

    URLFetch 是远程请求,当然很慢 :)
    darasion
        5
    darasion  
    OP
       2010-12-19 22:55:12 +08:00
    @jeeson 光是判断 401 不行。

    因为如果一个用户 protect 了它自己的推。而持有 token 的用户并没有通过这个用户的验证,那么这个这个持有token的用户用他的 token 访问 statuses/user_timeline 的时候仍然会返回 401 。即便这token是有效的。

    所以并不是只有当 token 无效时返回才返回 401 。
    jorakura
        6
    jorakura  
       2010-12-20 10:38:07 +08:00
    > 1、taskqueue 限量很少(好像是10万次调用),如果实体很多很多,太容易超限了。我只测试了几次就用掉了1%。

    我这边显示:20,000,000
    darasion
        7
    darasion  
    OP
       2010-12-20 10:58:41 +08:00
    @jorakura 您那是:Billing Enabled Quota ,我说的是Free Quota
    Livid
        8
    Livid  
    MOD
       2010-12-21 05:19:55 +08:00
    MapReduce。

    V2EX 用来清理数据的办法,源代码里有。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3143 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 15:18 · PVG 23:18 · LAX 08:18 · JFK 11:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.