【问题标题】:How does cassandra find the node that contains the data?cassandra如何找到包含数据的节点?
【发布时间】:2015-10-18 15:16:02
【问题描述】:

我已经阅读了很多关于 Cassandra 的文章和很多关于 SO 的问题/答案,但我仍然无法弄清楚 Cassandra 在读取数据时如何决定去哪个节点。

首先,关于虚拟集群的一些假设:

  1. 复制策略 = 简单
  2. 使用随机分区器
  3. 10 个节点的集群
  4. 复制因子为 5

以下是我根据我阅读的各种 Datastax 文章和其他博客文章对写入工作原理的理解:

  • 客户端将数据发送到随机节点
  • “随机”节点是根据主键的 MD5 哈希值决定的。
  • 数据写入 commit_log 和 memtable,然后传播 4 次(RF = 5)。

  • 然后选择环中的 4 个下一个节点并将数据持久保存在其中。

到目前为止,一切都很好。

现在的问题是,当客户端向集群发送读取请求(比如 CL = 3)时,Cassandra 如何知道它需要联系哪些节点(最坏的情况是 10 个节点中的 5 个)才能获得这个数据?当然它不会用到所有 10 个节点,因为那样效率很低。

我是否正确假设 Cassandra 将再次对(请求的)主键进行 MD5 哈希并根据该哈希选择节点然后遍历环?

另外,网络拓扑案例是如何工作的?如果我有多个数据中心,Cassandra 如何知道每个 DC/Rack 中的哪些节点包含数据?据我了解,只有第一个节点是明显的(因为主键的哈希已明确导致该节点)。

对不起,如果问题不是很清楚,如果您需要有关我的问题的更多详细信息,请添加评论。

非常感谢,

【问题讨论】:

    标签: cassandra cassandra-2.0


    【解决方案1】:

    客户端将数据发送到随机节点

    看起来可能是这样,但实际上有一种非随机的方式可以让您的驱动程序选择一个与之对话的节点。该节点称为“协调节点”,通常基于具有最小(最近)“网络距离”来选择。客户端请求实际上可以发送到任何节点,首先它们将发送到您的驱动程序知道的节点。但是一旦它连接并理解了集群的拓扑结构,它可能会变成一个“更接近”的协调器。

    集群中的节点使用Gossip Protocol 相互交换拓扑信息。 gossiper 每秒运行一次,并确保所有节点都与来自您配置的 Snitch 的数据保持同步。告密者会跟踪每个节点所属的数据中心和机架。

    这样,协调节点也有关于哪些节点负责每个令牌范围的数据。您可以通过从命令行运行 nodetool ring 来查看此信息。虽然如果您使用的是 vnodes,这将更难确定,因为所有 256 个(默认)虚拟节点上的数据都会在屏幕上快速闪烁。

    假设我有一张表,我用它来按名字跟踪船员,假设我想查找 Malcolm Reynolds。运行此查询:

    SELECT token(firstname),firstname, id, lastname 
    FROM usersbyfirstname  WHERE firstname='Mal';
    

    ...返回这一行:

     token(firstname)     | firstname | id | lastname
    ----------------------+-----------+----+-----------
      4016264465811926804 |       Mal |  2 |  Reynolds
    

    通过运行nodetool ring,我可以看到哪个节点负责这个令牌:

    192.168.1.22  rack1       Up     Normal  348.31 KB   3976595151390728557                         
    192.168.1.22  rack1       Up     Normal  348.31 KB   4142666302960897745                         
    

    或者更简单,我可以使用nodetool getendpoints查看这些数据:

    $ nodetool getendpoints stackoverflow usersbyfirstname Mal
    Picked up JAVA_TOOL_OPTIONS: -javaagent:/usr/share/java/jayatanaag.jar 
    192.168.1.22
    

    有关更多信息,请查看上面链接的一些项目,或尝试运行nodetool gossipinfo

    【讨论】:

    • 这是否意味着每个 Cassandra 节点都保留了所有令牌范围到节点映射的列表?澄清一下,如果我有 10,000 个节点并且每个节点有 256 个令牌,那么每个节点需要记住 10,000*256 个不同的分配吗?这些信息存储在哪里?
    • @JaySullivan 是的,查看 system.peers 表。
    【解决方案2】:

    Cassandra 使用一致的哈希将每个分区键映射到一个令牌值。每个节点都拥有一系列令牌值作为其 primary 范围,因此每个可能的哈希值都将映射到一个节点。然后以系统的方式保留额外的副本(例如环中的下一个节点)并存储在节点中作为它们的 secondary 范围。

    集群中的每个节点都知道整个集群的拓扑结构,例如哪些节点在哪个数据中心,它们在环中的什么位置,以及每个节点拥有哪些令牌范围。节点使用 gossip 协议获取和维护这些信息。

    当一个读请求进来时,被联系的节点成为读的协调者。它将计算哪些节点具有请求分区的副本,然后选择所需数量的节点以满足一致性级别。然后它将向这些节点发送请求并等待它们的响应并根据列时间戳合并结果,然后再将结果发送回客户端。

    【讨论】:

      【解决方案3】:

      Cassandra 将根据 partitioner 映射到令牌值的 partition key 定位任何数据。令牌是有限 令牌环 值范围的一部分,其中环的每个部分都由集群中的一个节点拥有。拥有某个令牌范围的节点被称为该令牌的主节点。副本将由数据复制策略选择。基本上,这是通过在令牌环中顺时针移动,从主节点开始,并根据所需副本的数量而停止。

      需要意识到的重要一点是,集群中的每个节点都能够根据上述逻辑识别出负责某个密钥的节点。每当将值写入集群时,接受请求的节点(协调节点)将立即知道需要执行写入的节点。

      在多个数据中心的情况下,所有键将跨所有 DC 映射到由分区器确定的完全相同的令牌。 Cassandra 将尝试写入每个 DC 和每个 DC 的副本。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-10
        • 2011-07-24
        • 1970-01-01
        • 2018-07-25
        • 2014-10-05
        • 2019-01-15
        • 2016-12-03
        • 2014-08-28
        相关资源
        最近更新 更多