【问题标题】:Avoid MemcacheService race condition in email service避免电子邮件服务中的 MemcacheService 竞争条件
【发布时间】:2014-04-19 15:10:57
【问题描述】:

Image 我的服务器提供了我正在使用 memcache 的电子邮件服务。当发件人向用户 X 发送新电子邮件时,X 的密钥将从缓存中删除。当用户 X 调用 getInbox 时,响应将添加到 X 的键下的缓存中(以便后续调用 getInbox 时返回相同的响应,直到发送者删除键并继续处理)。所以一个非常简单的设计。但是当 X 正在阅读某个发件人正在向 X 发送电子邮件的同时会发生什么?根据我的理解, putIfUntouched 和 getIdentifiable 在这里没有帮助。因为它们似乎只有在我在 putIfUntouched 中使用 getIdentifiable 返回的完全相同的实例/值时才有效,这在我的情况下是不可能的,因为我正在谈论两个不同的服务调用。那么有人知道我如何在我的简单模型中避免竞争条件吗?

更新

鉴于@AndreiVolgin 的回复,让我添加一些我认为是竞争条件的细节:

发送者的工作是移除密钥;收件人的工作是 1) 使用 syncCache.get(key) 读取值,2) 如果值为 null,则使用 syncCache.put(key, value) 将键设置为实际值。问题在于发送试图将值设置为空,而同时接收者正在调用syncCache.put(key, value)。如果收件人在设置为value 时获胜,那么收件人可能永远无法看到发件人所做的更改。

【问题讨论】:

    标签: java google-app-engine memcached


    【解决方案1】:

    这不是竞争条件。用户在查看收件箱之前的几毫秒内根本看不到发送给他的消息。

    没有办法避免这种情况,也没有理由避免这种情况。如果消息在您调用 Memcache 后 1 毫秒而不是在此 Memcache 调用前 1 毫秒发送,该怎么办?用户不会同样不高兴吗?

    更新:

    基于 OP cmets,一个进程使用 memcache 设置一个标志(没有新消息),而另一个进程在新消息到达时将其删除。如果新消息因为与用户设置标志同时出现而未能删除标志,则新消息将不可见,直到下一条消息到达。

    虽然极为罕见,但这是一个合理的担忧。在我看来,解决方案是在标志上设置一个过期时间,作为这种罕见情况的故障保险。

    【讨论】:

    • 感谢您的回复。但是我担心发件人由于交错而无法删除密钥的情况,在这种情况下,没有来自收件人的pull-to-refresh次数将传递新消息。在这种情况下,如果几天内没有发送其他新邮件,收件人将永远不会看到最后发送的邮件
    • 您可以为 Memcache 中的键设置过期时间。您正在描述一个非常罕见的用例,因此设置到期日期将作为此类情况的故障保险。
    • 再次感谢。如果这是唯一的方法,那就是这样。问题是 memcache 有可能为我节省很多钱,并且设置一个合理的到期日期只会给我的设计带来麻烦。另一方面,虽然这种并发错误似乎很少见,但在我的情况下,问题不是发生频率高,而是对受影响的个人的潜在破坏性影响。但也许我可以惹恼一些用户。
    • 可以计算概率。此外,到期时间只会影响在到期时间内未收到任何消息的帐户。至于成本,请使用现在几乎没有成本的仅键查询。在这种情况下,你甚至不需要使用 memcache。
    • 我不确定仅键查询是否可以在这里工作,因为我正在检查特定用户是否自时间戳 x 以来收到了邮件。据我了解,仅键查询不带条件。我错了吗?
    猜你喜欢
    • 2011-03-24
    • 1970-01-01
    • 2015-09-10
    • 2015-01-30
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 2010-09-25
    • 2019-06-12
    相关资源
    最近更新 更多