Cassandra修补了一个意外结果的List

时间:2018-03-12 17:56:58

标签: cassandra cassandra-3.0

我在修补C *中的LIST时做了一个观察,并希望有人可以给我一个暗示,如果有一个合理的解释(忽略用例实际上是有效的)。

假设一个简单的表只有一个主键和一列类型列表。

CREATE TABLE ks.tbl(col_primary varchar,varchar_list list<varchar>,PRIMARY KEY(col_primary)) ;

向该表添加一行,其中包含表中某些条目的列表。

INSERT INTO ks.tbl (col_primary,varchar_list) VALUES ('0815',['OlencUIkqqlVOFPiwsoEJM','JamilUOHIOXTWuGp','AbdulvZaeQDJOdu','GoldaGugnVNnbdSBpRpd','BrennaVvYuDyERsKvVW','FletcherpkkCYpEBket','DaytonglCSvswZQTEj','EdTUkTShUerYcfiSvCIH','LandenLTThnmlAAULJwdNwAma','IsabellelrDcMFHsyBGT','ArielOhIcLglehg','BellrtifChchjMZ','EmelieDdlViBlHUPQbxyUC']);

最后使用以下条目更新行。

UPDATE ks.tbl SET varchar_list[1]=null,varchar_list[0]='MEGGCJOFic',varchar_list=varchar_list+['nwbaGsGbcd'] WHERE col_primary='0815' IF EXISTS;

列表的预期输出是(实际上大部分时间都是)

['MEGGCJOFic', 'AbdulvZaeQDJOdu', 'GoldaGugnVNnbdSBpRpd', 'BrennaVvYuDyERsKvVW', 'FletcherpkkCYpEBket', 'DaytonglCSvswZQTEj', 'EdTUkTShUerYcfiSvCIH', 'LandenLTThnmlAAULJwdNwAma', 'IsabellelrDcMFHsyBGT', 'ArielOhIcLglehg', 'BellrtifChchjMZ', 'EmelieDdlViBlHUPQbxyUC', 'nwbaGsGbcd']

现在将此应用于具有两个数据中心(美国,欧盟)的设置,并使用一致性级别LOCAL_ONE并使用一个数据中心进行更新,另一个用于读取返回的令人惊讶的结果:

 ['MEGGCJOFic', 'nwbaGsGbcd']

这正是改变的两个要素。一段时间后,列表自行解析并返回预期的内容。

但如何进入如上所述的中间状态呢?同样的事情顺便说一句。如果使用MAPS而不是LIST。我确实知道数据是如何在C *中为集合实际布局的,但是如何才能使一个集群只包含更新而不包含原始数据呢?

1 个答案:

答案 0 :(得分:4)

它说明了Cassandra(C *)实际上是如何工作的以及它的内部架构。如果您使用C *更多,并且随着时间的推移,您将更多地了解它及其行为。有很多要解释但我会提到一些具体要点,并试着向你说清楚。

C *如何存储数据

How is data updated

CAP定理

Cassandra and CAP

  
    

Cassandra通常被归类为AP系统,这意味着可用性和分区容忍度通常被认为比Cassandra中的一致性更重要。但是,Cassandra可以通过复制因子和一致性级别进行调整,以满足一致性。

  

C *最终一致性:

  
    

最终一致性是分布式计算中使用的一致性模型,用于实现高可用性,非正式地保证,如果没有对给定数据项进行新的更新,最终对该项的所有访问都将返回最后更新的值。

  

C *一致性等级:

RF - &gt;将保留多少份数据(行)。 (有多少服务器或节点将保留相同的行/数据)。

CL - &gt;确认需要多少个节点才能让客户端知道/通知写/读操作是否成功。这意味着至少提到CL的节点数量(例如:如果CL是2个至少2个节点)必须确认/确保他们已成功写入数据或从这些副本中读取数据(等待所有必需的副本返回(协调器节点的结果)并合并结果(如果不同节点具有相同数据的不同更新,则保留最新数据)并成功将结果返回给客户端。

由于您的CL是LOCAL_ONE,因此只需要确认本地DC中的一个节点,该副本可以保存回溯数据或旧数据,但最终会得到更新。您可以使用LOCAL_QUORUM来获取一致的数据。对于集合,数据存储略有不同。

Using the Collections

  
    

这些更新操作在内部实现,没有任何先读后读操作。在列表中追加和添加新元素只会写入新元素。

  

摘要&amp;可能性

C *是面向行的DB。它存储映射到其相应键的多行数据(列)。 C *在写入之前不执行读取因此使得数据库中可能存在同一行的许多版本。在请求读取时,协调器完成合并它的不同版本的工作,比较时间戳并返回最新的时间戳。它取决于CL需要确认多少节点并将结果返回给协调器。如果您使用CL(写入CL +读取CL&gt; RF),您将获得最新结果。

例如:假设您有一个列表[1,2,3]。现在想要追加[4]。您的预期结果是[1,2,3,4]。当您使用LOCAL_ONE并且协调器节点命中仅具有此新更新的副本时,从而返回此结果。

如果您在写入操作后立即读取也会得到不一致的结果。对于下一次阅读,您将获得更新/最新的合并行。

在分布式系统中,这些是常见的场景,对于RDMS架构而言非常不寻常。

部分链接:

您还可以看到C *读写路径

The write path to compaction
How is data read?
4 node setup in cassandra is as same as 3 node setup
Understanding How CQL3 Maps to Cassandra's Internal Data Structure