我应该如何处理SimpleDB中的最终一致性,特别是在单元测试方面?

时间:2009-09-05 13:32:37

标签: unit-testing tdd amazon-simpledb eventual-consistency

我们正在Amazon Web Services堆栈上构建一个Web应用程序,到目前为止我很喜欢它。

我们也在充分利用测试驱动的开发,这也证明是非常棒的。

我只是希望有人可以帮助我解决我遇到的与Amazon SimpleDB的“最终一致性”相关的问题。

问题的最佳示例是在单元测试中添加用户,然后通过调用获取新添加的用户来检查用户是否已成功添加。

我可以轻松地继续前进,只是为此编写测试并且它可以正常工作,但我知道“最终的一致性”以及当我拨打电话获取用户时,用户可能不会实际上已经添加了。显然,如果调用fetch用户函数并且用户不在系统中,它将返回false或失败。

我想知道的是处理这个问题的最佳方法是什么?我已经看到了建立一个函数的建议,这个函数在请求之间休眠5秒并尝试10次。我也看到过具有指数退避的解决方案。什么是最佳解决方案?

3 个答案:

答案 0 :(得分:5)

我建议不要使用实际的SimpleDB服务对您自己的代码进行单元测试。您将测试您的代码+ SimpleDB客户端+网络+ SimpleDB本身。你需要的是模拟SimpleDB客户端来运行单元测试。这样您只需测试需要测试的代码。如果数据库在代码的单元测试中工作,测试驱动开发会要求测试。

如果您正在测试自己的SimpleDB客户端代码,则可以使用模拟SimpleDB服务或M/DB之类的东西,这是一个可以在本地运行的SimpleDB克隆。

但这会带来更大的问题,因为SimpleDB提供了最终的一致性而不是读写一致性。您的代码绝对需要能够处理新添加的项目不会立即从get或查询返回的事实。

我没有理由认为您的代码无法处理它。我只是说当你遇到像测试这样的问题时,作为一般规则,它暗示了需要考虑的代码需要考虑的问题。您可能会发现在应用程序代码和SimpleDB之间需要一个通用的缓存层,或者您可能需要一个可以提供读写一致性的会话缓存。

答案 1 :(得分:0)

您是在测试数据库还是反对它的代码?如果您正在测试针对数据库的代码,那么您应该具有期望代码添加用户的测试,然后不会返回用户,比如说,已经过了一些随机时间。显然,使用假数据库可以很容易地设置这个数据库,该数据库跟踪自上次请求以来的时间量,并且仅在初始请求过去后的指定时间之后返回预期值。您可以进行类似的测试,其中假设设置为永不返回值,设置为立即返回,等等。检测假冒以跟踪交互情况,您可以在测试中设置您希望代码的方式行为,以便您的代码遵循预期的行为(例如,轮询至少两次)。

答案 2 :(得分:0)

首先,正如@Mocky所说,在单元测试中击中真实数据库是错误的。您可以在集成测试中执行此操作,但这些可以工作,因为所有单元测试都通过了。

关于了解最终一致性的单元测试,这里有一些想法:

  1. 测试用户在写完后从simpledb返回(没有e-c的影响) 把用户 得到用户 测试相同性

  2. 测试用户在写入后没有从simpledb返回(e-c效果) 把用户 得到用户 接受错误

  3. 测试来自ec的错误 得到用户+接受错误 处理测试错误

  4. 我正在考虑使用一层memcache(或elasticcache)来提供缓存用户,因此当用户写入simpledb时,它们也会被发送到缓存。当发生simpledb错误时,接下来在代码确定之前检查缓存,确实没有这样的用户。

    (实际上很想听听你对最后一段的看法)