经常遇到这样的事情:
有很多很多实体,有些实体保存的内容是有效的,有些是无效的。
现在要将那些无效的实体清理掉。
我暂时考虑到如下几点:
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、...
有很多很多实体,有些实体保存的内容是有效的,有些是无效的。
现在要将那些无效的实体清理掉。
我暂时考虑到如下几点:
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、...
