S.O*_*O.S 6 counter cassandra nosql scylla
根据官方文档,对计数器列的限制包括ScyllaDB:
The only other columns in a table with a counter column can be columns of the primary key (which cannot be updated). No other kinds of column can be included. This limitation safeguards correct handling of counter and non-counter updates by not allowing them in the same operation.\n\nAll non-counters columns in the table must be part of the primary key.\n\nCounter columns, on the other hand, may not be part of the primary key.\nRun Code Online (Sandbox Code Playgroud)\n在我的表设计中,我有数百行,其中每行都需要链接到一个计数器列。
\n该表具有以下结构:
\nK1 K2 C1 C2 C3 V1 V2 V3 COUNTER\nRun Code Online (Sandbox Code Playgroud)\n其中K是分区键,C是簇键,V是值,COUNTER是计数器列。
一般情况下,上表查询如下:
\nSELECT * from table WHERE K1 = A & K2 = B & C1 = X & C2 = Y & C3 = Z. \nRun Code Online (Sandbox Code Playgroud)\n这会导致每个查询返回大约 500 行。如图所示,每一行都链接到一个 COUNTER 列。具体来说,每个组合都K1, K2, C1, C2, C3链接到不同的COUNTER 值。
如果必须将 COUNTER 移至完全不同的表,我该如何对该表进行建模?
\n如果我理解正确,执行此操作的唯一方法是定义另一个表 ->table_counter不带任何值 ( V):
K1 K2 C1 C2 C3 COUNTER\nRun Code Online (Sandbox Code Playgroud)\n但是,我对这种方法有几个问题:
\n1)像这样分解一个逻辑上有凝聚力的表似乎非常不优雅
\n2)这意味着每当我想执行前一个查询时,我基本上需要执行两个查询,而不是一个,只是为了获取链接到每个查询的计数器信息K1 K2 C1 C2 C3组合的计数器信息
3)我还被迫将上面两个查询的结果合并到客户端的单个数据结构中(为了它有用)
\n它是否正确?如果是,是否有 COUNTER 列的替代方案,我可以将 COUNTER 列添加到第一个表中?
\n我想到的一种方法是使用常规INTEGER作为计数器列。每当需要更新计数器列时,我可以读取当前计数器(整数)值并在客户端递增它,然后将新值写回数据库。我知道我不会\xe2\x80\x99t受到并发读/写的保护,因此如果两个客户端同时读取计数器值,并且它们都递增/更新它,则一次写入(更新)将丢失(例如,仅保留最后一次写入)。然而,我可以忍受偶尔丢失的写入,因为我们没有跟踪任何关键的东西,其中单个(或少数)丢失的写入会产生重大影响。我还知道,每次我想更新计数器列时,这都需要读取和写入(两个操作),但是,它允许我将计数器列保留为原始表的一部分,并减少查询两张桌子合一张。此外,通过这种设计,无需在客户端合并查询两个表的结果。看起来比使用柜台柱更有效,也更优雅。
这种方法是 COUNTER 列的可行替代方案吗?有没有我错过的陷阱?在我的示例中是否有另一种方法可能效果更好?
\n谢谢
\n“经典”DRDT 启发的(但不完全是)计数器列的替代方案是使用 Scylla 的轻量级事务(LWT) - 基本上,您的计数器变成一个普通的整数列,如果您愿意,您可以正常读取它,但写入时使用条件更新(更新...如果...)。例如,要修改值 V并增加计数器,您可以:
这种模式被称为“乐观锁定” - 步骤 1-2 是“乐观的”,假设他们构建的新项目将能够被写入,但如果其他一些并发更新击败了我们,则需要将步骤 1-2重复。这与悲观锁定方法形成对比,在悲观锁定方法中,客户端“获取锁定”,并且只有在知道自己持有锁定之后,才需要计算该项目的新值(步骤 2)。
LWT 比计数器强大得多,而且你可以用它做比计数器更多的事情。读取可以与常规读取一样高效,但请注意写入确实会变慢。Scylla 正在致力于基于 Raft 的下一代 LWT 实现(当前实现基于 Paxos),因此您可以期待未来 LWT 写入性能的改进。