如何使写操作幂等?

时间:2010-04-08 06:04:42

标签: scalability idempotent

我正在阅读一篇关于Twitter(http://engineering.twitter.com/2010/04/introducing-gizzard-framework-for.html)最近发布的Gizzard分片框架的文章。它提到所有写操作必须是幂等的,以确保高可靠性。

根据wikipedia,“幂等操作是可以多次应用而不改变结果的操作。”但是,恕我直言,在Gizzard案例中,幂等写操作应该是顺序无关紧要的操作。

现在,我的问题是:如何使写操作具有幂等性?

我唯一可以想象的是每次写入附加一个版本号。例如,在博客系统中,每个博客都必须包含 $ blog_id $ content 。在应用程序级别,我们总是写博客内容,如写($ blog_id,$ content,$ version)。确定 $ version 在应用程序级别是唯一的。因此,如果应用程序首先尝试将一个博客设置为“Hello world”而第二个想要将其设置为“Goodbye”,则 write 是幂等的。我们有两个写操作:

write($blog_id, "Hello world", 1);
write($blog_id, "Goodbye", 2);

这两个操作应该更改DB中的两个不同记录。因此,无论执行这两个操作的次数和次序,结果都是相同的。

这只是我的理解。如果我错了,请纠正我。

2 个答案:

答案 0 :(得分:6)

你是对的。幂等操作本身只能提供一种冲突解决模式 - “最后写入获胜”。如果您的写入无法及时重新排序,那么这是一种可能的解决方案。如果可以,您应该提供其他信息以自动解决冲突。而你的想法并不新鲜。在一般情况下,它被称为vector clocks

我们在我们的一个系统中使用基于版本的冲突解决方案来收集系统中对象的更改历史记录。客户端将完整对象状态和版本信息发送到历史记录模块(异步)。然后,历史记录模块可以以正确的方式对对象状态进行重新排序,并仅在持久存储中保存增量。唯一的限制是客户端在对对象进行更改时应该使用某种并发控制(如果跟踪对象状态版本,optimistic locking是非常好的方法)。

答案 1 :(得分:3)

你有正确的想法。设置特定值是幂等的,因为如果您多次执行该操作,则会得到相同的结果。经典的非幂等写入是一个追加,因为重复会导致附加多个副本。

另请参阅此previous stackoverflow question