【问题标题】:consistency level tuning in cassandracassandra 中的一致性级别调整
【发布时间】:2014-09-16 12:48:08
【问题描述】:

想象一个电子商务应用程序:

假设我有三个 Node cluster N1, N2, N3. 并且我的一致性级别 (CL) 很弱: 那就是

Read CL = N/2+1 = 2 (in this case), Write CL = Any (alteast 1)

我有一个产品表,例如

这是跨三个节点同步的初始数据

 product_info : { 'computer': 1}
  1. 现在客户端 A 从 N1 读取信息,客户端 B 从 N1 读取信息 N2

    客户端 1 发现有 1 台计算机可用

    客户端 2 发现有 1 台计算机可用

  2. 现在他们俩都去买了,客户 A 先下订单。所以 N1,表格将如下所示:

    product_info : {'computer':0}

  3. 现在客户 2 在 N2 下订单,表格看起来像 以下:

    product_info : {'computer':0}

    但实际上客户 2 的订单不应该被处理。

  4. 客户端 C 通过 N3 访问。现在在 N1 完成读取 返回 0。(因为 quorum 至少有 2 个节点应该响应) N3 值为 1,但其时间戳已过时。所以它会更新它的 值并向客户显示没有可用的计算机。这个不错

    在这个例子中,弱一致性和强一致性级别都会导致错误的结果,仅仅是因为在客户端A和B加载第一个product_info的时候,数据是同步的。这在 Cassandra 中如何处理?

【问题讨论】:

    标签: cassandra consistency eventual-consistency


    【解决方案1】:

    你没有提到你的复制因子。

    如果您的读取一致性 + 写入一致性 > 复制因子,您将立即获得一致性。

    假设您的复制因子是 3。为了立即一致性和 RC = 2,您需要至少 2影响可用性,因为一个节点出现故障意味着您无法读取。

    即时一致性意味着您将阅读所写的任何内容。即成功写入后,没有读取将读取先前的值。但是,这不会阻止您的应用程序使用它之前读取的值。

    在这种情况下,您可以使用轻量级事务。更新.....如果[某些情况。]。这将执行较慢,但可能足以满足您的用例。

    很多时候,特别是在分布式场景中,最好处理失败——甚至将其作为商业案例——而不是试图阻止任何“坏事”的发生。像这样的边缘案例是与企业对话并发现隐藏机会的机会:

    • 如果我们超量预订商品会怎样?
    • 是取消订单更好,还是让客户知道他们的订单不可避免地被延迟了,可能会进行销售并给他们一张礼券。
    • 我们能否给客户一台稍微好一点的电脑,但利润会受到轻微影响?这可以帮助我们进行销售,让客户满意,并可能给我们带来回报。戴尔经常这样做。
    • 我们可以打电话给客户并解释可能追加销售的情况吗?

    我们甚至可以接受订单并在我们发现问题时通知一位客户 - 我在亚马逊上亲眼目睹了这一点。

    如果我们绝对必须防止在卖出时出现任何超卖现象,那么也有这样的模式。我们可以使用 raft 甚至 zookeeper 之类的分布式锁来处理 cassandra 之外的协调。我们还可以为每个项目实现带有 TTL 的逻辑锁 - 使用 TTL 来确保杂乱的代码不会弄乱库存。

    这实际上取决于您想要的保证字符串,以及您愿意经历多少麻烦来实现这一点。更重要的是,如果解决它不是更多有利可图。

    希望对您有所帮助。

    【讨论】:

    • 写入期间立即一致性会发生什么情况:假设三分之二的节点不在网络中。客户端的写入是否成功?我的意思是写在客户端级别失败,因为他被指示了。但是一个节点(三个中的一个)已经覆盖了值
    • 如果 WC 为 2,则至少 2 个副本必须确认写入,客户端才能接收成功。因此,如果一个分区的两个副本节点以 3 的复制因子关闭,如果指定 WC = 2,则写入将失败。在读取的情况下也是类似的——n=RC 节点必须响应读取才能成功。这是一种为了一致性而交易可用性的方式。
    • 就客户端而言,写入失败。但是其中一个节点已经写入了值并且没有回滚功能。所以当失败的节点回来时,它会通过 gossip 获取最新的值。在实际执行查询时,客户端认为它好像失败了。
    • 我可能是错的,但看起来不成功的提交没有应用。只需设置一个集群,并尝试该场景。似乎没有从任何节点返回“不成功”的写入,即使是读取一致性之一。现在这可能是由于协调器已经知道副本已关闭并且没有发出写入...我会尝试找到确切的原因,如果总是这样。
    • 更新:看来我的演示“工作”的原因是因为有关宕机节点的信息是通过八卦传播的,如果协调器知道节点宕机,它根本不会发出请求。如果发出请求,则节点死亡,那么您描述的场景可能会发生。客户端写入失败的建议是重试。这通常没问题,因为插入和更新基本上是 upsert。不过要小心会反列。使用的解决方法无疑将取决于您的用例和所需的保证级别。
    猜你喜欢
    • 2018-06-13
    • 2016-07-05
    • 2017-01-09
    • 1970-01-01
    • 2021-05-07
    • 2018-07-26
    • 2017-05-06
    • 2014-09-19
    • 1970-01-01
    相关资源
    最近更新 更多