我们在Google App Engine中运行了一个应用程序,作为其操作的一部分,它会生成序列号。这些数字必须符合以下标准:
我们编写的代码试图确保生成的数字是全球唯一的,但我不能共享该代码,因为a)它相当复杂,b)它的属性是我的雇主和c)它似乎没有在重负荷下工作。
我已经完成了一些阅读,因为未能确保我们符合独特标准,并找到了有关sharded counters的一些信息,但我认为这种方法可能有助于我仍然没有&# 39;认为它可以保证我们100%肯定会产生独特的序列。我怀疑在数据存储区中存在一些延迟,当涉及到upserts时,更新的计数器与后续读取中反映的更新之间的延迟是罪魁祸首。除了没有处理分片的PHP示例(虽然我们可能从其他示例中找出它,如果有一个有效的PHP示例,那将是很好的)。
我建议的解决方案如下:
从表面上看,这似乎是一个合理的解决方案,但我担心仍然存在边缘情况,我们最终得到不一致的计数器值,特别是如果同时发生大量更新。虽然Memcache将确保返回值的原子性,但我不确定对数据存储的写入是否会按请求的顺序发生,并且在数据存储结束时数据存储可能无法反映Memcache中可能导致问题的值如果应用程序关闭,并且在恢复服务时从数据存储区加载了错误的值。
数据存储区写入是否按照收到的顺序应用?我可以保证在执行完所有写操作后,Datastore中的值与Memcache中的值匹配吗?有没有更好的解决方案来解决这个问题(除了切换到具有自动增量/序列支持的SQL数据库)?
答案 0 :(得分:0)
AppEngine数据存储区中的顺序ID是一个难以解决的问题。
如果您尝试使用持久性数据存储区逐个执行此操作,那么您将达到事务吞吐量限制。
我能想到的最佳方法:
nds
包或以类似方式执行)并通过键从数据存储区获取所有碎片值。基本上在Go中只需为所有分片调用nds.GetMulti()
。锁应具有合理的到期值。对于nds包来说,这是30秒。基本上你可以在没有memcache的情况下完成,但是memcache可以节省你的钱并且可以减少延迟(或不减少)。
重要的是先锁定内存缓存并更新数据存储,然后从内存缓存中删除或使用CAS进行更新。你的计划相反。