以编程方式在 plone 上创建内容类型时, time.time() 是一种安全的方法吗?
我必须在 Plone 上使用 _createObjectByType
。我将对象的 id 作为参数。在这种情况下,基于 time.time()
创建一个 id 来避免冲突是否安全?两个请求是否可以具有完全相同的时间戳(如 time.time()
所示)?
I have to use _createObjectByType
on Plone. I have as an argument the id
of the object. Is it going to be safe, in this scenario, to create an id based on time.time()
to avoid collisions? Can two requests have exactly the same timestamp as shown by time.time()
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这样做是完全安全的,即使在不太可能发生的情况下,两个请求完全同时处理,如果发生冲突,ZODB 将引发 ConflictError 并重试您的请求。
回应下面的讨论:
在一台计算机上,根据定义,两个事务必须重叠(在每个线程中从 time.time() 得到相同的结果。)ZODB 是 MVCC,因此每个线程都会看到数据库的一致视图。是交易开始的时间。当第二个线程提交时,将引发冲突错误,因为它将写入自事务开始以来已更改的对象。
如果您的客户端在多台计算机上运行,那么您需要考虑客户端之间时钟漂移的可能性。对于其事务 id,ZODB 选择当前时间戳或最后事务 id + 1 中较大的一个。
但是,也许您应该考虑根本不使用时间戳作为 id,因为它会导致重负载下的冲突,因为所有请求都希望在同一个 BTree 存储桶中创建条目。随机选取 id 将消除几乎所有冲突,但会导致 BTree 填充效率低下。推荐的方法是每个创建对象的线程从数字空间中的随机点开始并按顺序创建 id。如果它发现某个 id 已被使用,那么它应该随机选择数字空间中的另一个点并从那里重新开始。我相信 zope.intid 包含此策略的实现。
You'll be perfectly safe doing this, even in the unlikely event two requests are processed at exactly the same time, in event of a conflict the ZODB will raise a ConflictError and retry your request.
Responding to the discussion below:
On a single computer then by defition both transactions must overlap (you got the same result from time.time() in each thread.) ZODB is MVCC, so each thread sees a consistent view of the database as it was when the transaction began. When the second thread commits, a conflict error will be raised because it will write to an object that has changed since the beginning of the transaction.
If you have clients running on multiple computers then you need to think about the possibility of clock drift between the clients. For its transaction ids, ZODB chooses whichever is the greater of either the current timestamp or the last transaction id + 1.
However, perhaps you should consider not using a timestamp as an id at all, as it will lead to conflicts under heavy load, as all requests will want to create entries in the same BTree bucket. Picking ids randomly will eliminate almost all of the conflicts, but will lead to inefficiently filled BTrees. The recommended approach is for each thread that creates objects to start at a random point in the number space and create ids sequentially. If it finds that an id has already been used then it should randomly pick another point in the number space and start again from there. I believe zope.intid contains an implementation of this strategy.