关于我的用例的简要概述:考虑一个具有一百万个条目的数据库(很可能是 mongodb)。每个条目的值需要每天通过调用 API 进行更新。如何设计这样的cronjob?我知道 Facebook 也有类似的做法。我唯一能想到的就是有多个作业,将数据库条目分成批次,每个作业更新一个批次。我确信那里有更聪明的解决方案。我也不确定使用什么技术。任何建议表示赞赏。
-卡兰
鉴于“保持缓存温暖”的更新问题上下文,除非该数据能够舒适地放入可用内存中,否则接触所有数据库文档的策略可能会减少而不是提高性能。
MongoDB 中的缓存依赖于文件系统缓存的操作系统行为,这通常通过遵循最近最少使用 (LRU) 方法来释放缓存。这意味着随着时间的推移,内存中的工作数据集自然应该是“温”数据。
如果您强制将数据读入内存,您可能会加载最终用户很少(或从不)访问的文档......可能会以牺牲应用程序用户实际上可能更频繁地请求的数据为代价。
有一个“预热”缓存的用例..例如,当您重新启动 MongoDB 服务器并希望将数据或索引加载到内存中时。
在 MongoDB 2.2 中,您可以为此目的使用新touch
命令。
其他预热策略本质上是使用explain()
. 与其尝试最小化索引条目 ( nscanned
) 和文档 ( nscannedObjects
) 的数量,不如编写一个有意最大化这些条目的查询。
根据您的 API 响应时间目标.. 即使某人的初始调用需要将他们的数据提取到内存中,这仍然应该是一个相当快速的索引检索。除非您的应用程序有很多处理开销,否则 3 到 4 秒响应的目标似乎很慷慨:MongoDB 中默认的“慢”查询值为 100 毫秒。
从技术角度来看,您可以在 mongodb shell 中执行脚本,并通过 cron 执行它们。如果您安排 cron 运行如下命令:
./mongo server:27017/dbname--quiet my_commands.js
Mongodb 将执行 my_commands.js 脚本的内容。现在,举一个过于简单的例子来说明这个概念。如果您想找到一个名为sara
并插入属性的人(是的,不切实际的示例),您可以在.js
脚本文件中输入以下内容。
person = db.person.findOne( { name : "sara" } );
person.validated = "true";
db.people.save( person );
然后每次 cron 运行时,该记录都会更新。现在,给你的 api 添加一个循环和一个调用,你可能会有一个解决方案。有关这些命令和示例的更多信息可以在mongodb 文档中找到。
但是,从设计的角度来看,您确定需要每晚更新每条记录吗?有没有办法确定需要处理的更合理的记录子集?或者,当数据被检索并提供给将要使用它的任何人时,是否可以在数据上调用 api?