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

2010-12-19 16:02:48 +08:00
 darasion
经常遇到这样的事情:
有很多很多实体,有些实体保存的内容是有效的,有些是无效的。
现在要将那些无效的实体清理掉。

我暂时考虑到如下几点:
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、...
3900 次点击
所在节点    Google App Engine
8 条回复
julia
2010-12-19 16:58:07 +08:00
学习
jeeson
2010-12-19 21:27:03 +08:00
加上时间戳,最后的验证/使用时间,多少时间内的不需要再次验证,这样可以减少验证数量

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

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

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

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

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

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

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

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

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

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

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

V2EX 用来清理数据的办法,源代码里有。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/6053

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX