实现令牌缓存

时间:2014-04-09 04:34:46

标签: multithreading caching synchronization locking client-server

我正在尝试实现一个简单的缓存,其缓存只包含身份验证服务器返回给我的应用程序的最新令牌。有不同的工作线程试图同时登录到身份验证服务器。这增加了身份验证服务器的负载,并且我的应用程序变得很慢,因为每个身份验证线程都有一个涉及服务器的往返。因此,通过实现简单的令牌缓存,令牌将在客户端缓存,并且仅在其中一个身份验证线程无法登录时才会更新。失败的人将从认证服务器获取新令牌。

我遇到的问题是当任何身份验证线程失败并更新令牌缓存时,可能会有一些线程已经读取旧令牌并最终失败,他们也会尝试更新缓存。如何更新缓存后,如何阻止这些线程更新?

3 个答案:

答案 0 :(得分:1)

一种可能的解决方案是为检索到的令牌分配时间戳。时间戳不必是"真实",序列号就足够了。

当线程从令牌缓存中检索令牌时,它还会检索与令牌关联的序列号。当线程无法登录时,它首先必须再次检查本地缓存,以查看缓存是否已刷新,因为它已检索到其令牌。如果当前令牌的序列号与当前令牌的序列号不同,则可以使用缓存中的令牌再次尝试。

只有在登录失败并且自检索失败令牌以来尚未刷新缓存时,才需要更新令牌缓存。

序列号很可能会循环一个完整的循环,并且一个任务误导以为缓存没有刷新,实际上它有很多次,但这更像是一个理论上的可能性而非实际问题。

答案 1 :(得分:1)

当工作线程无法登录时,它应检查令牌缓存以查看令牌是否已从已发布的令牌更改。如果缓存的令牌已更改,则应使用新的缓存令牌,而不是寻找新令牌。

当工作线程确实寻找新令牌时,它也可以保留旧的,不再有效的令牌。然后在将新令牌放入缓存之前,它可以检查当前缓存的令牌是否与其旧令牌相同。

令牌缓存当然需要是线程安全的,并确保在其他线程中立即看到来自一个线程的更新,例如通过使用对缓存令牌的易失性引用。这比为每个令牌保留单独的时间戳更简单。

答案 2 :(得分:-1)

假设您的客户正在快速而且经常地行动,并且获得新令牌所需的时间可能比少数客户端请求长几倍,您必须引入某种锁定。

如果您认为,在2秒内收到该令牌,您可以设置以下规则:

使用带有键的缓存"令牌"并且"锁定"。

如果没有令牌内容,并且锁定为空,请设置"锁定"为True并尝试获取新令牌。完成后,删除锁并存储新令牌。

如果有令牌,请尝试使用它。

如果您拥有的令牌失败,请从缓存当前令牌获取,如果它不同,请尝试使用新值。如果没有令牌,并且"锁定"是真的,等待2秒再试一次。如果没有找到新的令牌,请尝试自己获取令牌(再次使用" lock" True)。

简而言之:

  • if" token"发现,尝试使用它
  • if" token"失败,从缓存中删除它并设置"锁定",获取新令牌,删除锁定。
  • 如果没有"令牌",请检查是否有"锁定",如果是,请等待2秒,获取新令牌(如果可用),如果不可用,请尝试获取自己的。