如何在Cassandra中实现单读者语义?

时间:2013-07-29 22:11:18

标签: multithreading synchronization locking cassandra distributed

目标

我有一张一次性代币表;最多一个线程应该能够读取任何给定的行。如果竞争条件的可能性很小,导致行根本不可读,则可以接受。

为什么

我正在OAuth2中实现授权代码流。服务器创建一个具有唯一ID的“身份验证代码”授权令牌,并将其交给客户端;客户很快回来并尝试将auth代码兑换成真正的访问令牌。这种救赎最多只能发生一次;如果攻击者获得了授权代码,但客户端首先将其赎回,则攻击者也无法将其兑换。

验证码最多10分钟后到期;我存储了一个到期时间戳列以检查兑换,但我也使用Cassandra的TTL功能(列到期)进行垃圾收集。

此处的所有操作均使用LOCAL_QUORUM执行。每个auth代码由一个行表示,其中一个键等于auth代码值。

不满意/破坏的解决方案

  • 计数器列
    • 维护一个用于授权代码兑换的计数器列。当线程尝试兑换authcode时,它首先递增计数器列中的auth代码行,然后读取auth代码的列。如果计数大于1,则拒绝。在竞争条件下,两个线程都可能拒绝。
    • 有效期:我相信只有全失败错误才能正常运行。
    • 下行:Cassandra does not support TTLs用于反列,这意味着我必须运行收割机进程。
  • DIBS
    • 维护一个名为“dibs”的字符串列。当线程尝试兑换auth代码时,它会将唯一ID写入dibs列,然后读取列。如果dibs值不再匹配,请拒绝。
    • 有效期:不。线程1写入,读取,接受。线程2写入,读取,接受。只能在读取后添加删除或第二次写入,这是不可修复的,因为这可能发生在其他线程的操作之后。

可能的解决方案

Lamport's bakery algorithm看起来很合适,但可能有点过分。

问题

我是否坚持使用计数器列进行合作单读卡器锁定?

1 个答案:

答案 0 :(得分:1)

这不是您问题的直接答案,但希望是有用的信息。

Cassandra 2.0将支持比较和交换 - 服务器端实现您的“dibs”方法,以确保一致性。从发行说明中,Cassandra 2.0和CQL for 2.0.1中的thrift支持此功能。

根据您的时间范围和可能使用x.0版本的意愿,这可能是一种解决方案。