cassandra如何找到包含数据的节点?
How does cassandra find the node that contains the data?
我已经阅读了很多关于 Cassandra 的文章和很多 question/answers,但我仍然无法弄清楚 Cassandra 在读取数据时如何决定去哪个节点.
首先,关于假想集群的一些假设:
- 复制策略=简单
- 使用随机分区程序
- 10 个节点的集群
- 复制因子 5
根据各种 Datastax 文章和我阅读的其他博客文章,这是我对写入工作原理的理解:
- 客户端将数据发送到随机节点
- "random"节点是根据主键的MD5散列决定的
数据被写入 commit_log 和 memtable,然后传播 4 次(RF = 5)。
然后选择环中接下来的4个节点并在其中持久化数据。
到目前为止,还不错。
现在的问题是,当客户端向集群发送读取请求(比如 CL = 3)时,Cassandra 如何知道它需要联系哪些节点(最坏情况下 10 个中有 5 个)得到这个数据?当然它不会去到所有 10 个节点,因为那样效率很低。
我假设 Cassandra 将再次对(请求的)主键进行 MD5 散列并根据它选择节点然后遍历环路是否正确?
另外,网络拓扑案例是如何工作的?如果我有多个数据中心,Cassandra 如何知道每个 DC/Rack 中的哪些节点包含数据?据我了解,只有第一个节点是显而易见的(因为主键的散列已明确导致该节点)。
抱歉,如果问题不是很清楚,如果您需要有关我的问题的更多详细信息,请添加评论。
非常感谢,
Cassandra 使用一致性哈希将每个分区键映射到令牌值。每个节点都拥有令牌值范围作为其 primary 范围,因此每个可能的哈希值都将映射到一个节点。然后以系统的方式保存额外的副本(例如环中的下一个节点)并存储在节点中作为它们的 secondary 范围。
集群中的每个节点都知道整个集群的拓扑结构,比如哪些节点在哪个数据中心,在环中的什么位置,每个节点拥有哪些令牌范围。节点使用八卦协议获取并维护此信息。
当读取请求进来时,联系的节点成为读取的协调器。它将计算哪些节点具有请求分区的副本,然后选择所需数量的节点以满足一致性级别。然后它会向这些节点发送请求并等待它们的响应,并在将结果发送回客户端之前根据列时间戳合并结果。
Client sends the data to a random node
这看起来可能是这样,但实际上有一种 non-random 方式让您的 driver 选择一个节点进行对话。这个节点被称为一个"coordinator node",通常选择based-on具有最少(最接近)"network distance."客户端请求真的可以发送到任何节点,首先它们将被发送到节点你的 driver 知道的。但是一旦它连接并了解您的集群的拓扑结构,它可能会变成 "closer" 协调器。
集群中的节点使用您配置的 Gossip Protocol. The gossiper runs every second, and ensures that all nodes are kept current with data from whichever Snitch 相互交换拓扑信息。告密者跟踪每个节点属于哪个数据中心和机架。
这样,协调节点也有关于每个令牌范围由哪些节点负责的数据。您可以从命令行通过 运行 a nodetool ring
查看此信息。尽管如果您使用的是虚拟节点,这将更难确定,因为所有 256 个(默认)虚拟节点上的数据将在屏幕上快速闪烁。
所以假设我有一个 table 用来通过他们的名字跟踪船员,假设我想 look-up Malcolm Reynolds。 运行 这个查询:
SELECT token(firstname),firstname, id, lastname
FROM usersbyfirstname WHERE firstname='Mal';
...returns 这一行:
token(firstname) | firstname | id | lastname
----------------------+-----------+----+-----------
4016264465811926804 | Mal | 2 | Reynolds
通过运行一个nodetool ring
可以看出是哪个节点负责这个token的:
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 Whosebug usersbyfirstname Mal
Picked up JAVA_TOOL_OPTIONS: -javaagent:/usr/share/java/jayatanaag.jar
192.168.1.22
有关更多信息,请查看上面链接的一些项目,或尝试 运行 nodetool gossipinfo
。
Cassandra 将根据分区键 由分区程序 映射到令牌值来定位任何数据。令牌是有限 令牌环 值范围的一部分,其中环的每个部分都由集群中的一个节点拥有。拥有某个令牌范围的节点被称为该令牌的主要节点。副本将由数据复制策略选择。基本上这是通过在令牌环中顺时针方向进行,从主节点开始,然后根据所需副本的数量停止。
需要注意的是,集群中的每个节点都能够根据上述逻辑识别出负责某个键的节点。每当向集群写入值时,接受请求的节点(协调器节点)将立即知道需要执行写入的节点。
在多个数据中心的情况下,所有 DC 上的所有密钥都将映射到由分区程序确定的完全相同的令牌。 Cassandra 将尝试写入每个 DC 和每个 DC 的副本。
我已经阅读了很多关于 Cassandra 的文章和很多 question/answers,但我仍然无法弄清楚 Cassandra 在读取数据时如何决定去哪个节点.
首先,关于假想集群的一些假设:
- 复制策略=简单
- 使用随机分区程序
- 10 个节点的集群
- 复制因子 5
根据各种 Datastax 文章和我阅读的其他博客文章,这是我对写入工作原理的理解:
- 客户端将数据发送到随机节点
- "random"节点是根据主键的MD5散列决定的
数据被写入 commit_log 和 memtable,然后传播 4 次(RF = 5)。
然后选择环中接下来的4个节点并在其中持久化数据。
到目前为止,还不错。
现在的问题是,当客户端向集群发送读取请求(比如 CL = 3)时,Cassandra 如何知道它需要联系哪些节点(最坏情况下 10 个中有 5 个)得到这个数据?当然它不会去到所有 10 个节点,因为那样效率很低。
我假设 Cassandra 将再次对(请求的)主键进行 MD5 散列并根据它选择节点然后遍历环路是否正确?
另外,网络拓扑案例是如何工作的?如果我有多个数据中心,Cassandra 如何知道每个 DC/Rack 中的哪些节点包含数据?据我了解,只有第一个节点是显而易见的(因为主键的散列已明确导致该节点)。
抱歉,如果问题不是很清楚,如果您需要有关我的问题的更多详细信息,请添加评论。
非常感谢,
Cassandra 使用一致性哈希将每个分区键映射到令牌值。每个节点都拥有令牌值范围作为其 primary 范围,因此每个可能的哈希值都将映射到一个节点。然后以系统的方式保存额外的副本(例如环中的下一个节点)并存储在节点中作为它们的 secondary 范围。
集群中的每个节点都知道整个集群的拓扑结构,比如哪些节点在哪个数据中心,在环中的什么位置,每个节点拥有哪些令牌范围。节点使用八卦协议获取并维护此信息。
当读取请求进来时,联系的节点成为读取的协调器。它将计算哪些节点具有请求分区的副本,然后选择所需数量的节点以满足一致性级别。然后它会向这些节点发送请求并等待它们的响应,并在将结果发送回客户端之前根据列时间戳合并结果。
Client sends the data to a random node
这看起来可能是这样,但实际上有一种 non-random 方式让您的 driver 选择一个节点进行对话。这个节点被称为一个"coordinator node",通常选择based-on具有最少(最接近)"network distance."客户端请求真的可以发送到任何节点,首先它们将被发送到节点你的 driver 知道的。但是一旦它连接并了解您的集群的拓扑结构,它可能会变成 "closer" 协调器。
集群中的节点使用您配置的 Gossip Protocol. The gossiper runs every second, and ensures that all nodes are kept current with data from whichever Snitch 相互交换拓扑信息。告密者跟踪每个节点属于哪个数据中心和机架。
这样,协调节点也有关于每个令牌范围由哪些节点负责的数据。您可以从命令行通过 运行 a nodetool ring
查看此信息。尽管如果您使用的是虚拟节点,这将更难确定,因为所有 256 个(默认)虚拟节点上的数据将在屏幕上快速闪烁。
所以假设我有一个 table 用来通过他们的名字跟踪船员,假设我想 look-up Malcolm Reynolds。 运行 这个查询:
SELECT token(firstname),firstname, id, lastname
FROM usersbyfirstname WHERE firstname='Mal';
...returns 这一行:
token(firstname) | firstname | id | lastname
----------------------+-----------+----+-----------
4016264465811926804 | Mal | 2 | Reynolds
通过运行一个nodetool ring
可以看出是哪个节点负责这个token的:
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 Whosebug usersbyfirstname Mal
Picked up JAVA_TOOL_OPTIONS: -javaagent:/usr/share/java/jayatanaag.jar
192.168.1.22
有关更多信息,请查看上面链接的一些项目,或尝试 运行 nodetool gossipinfo
。
Cassandra 将根据分区键 由分区程序 映射到令牌值来定位任何数据。令牌是有限 令牌环 值范围的一部分,其中环的每个部分都由集群中的一个节点拥有。拥有某个令牌范围的节点被称为该令牌的主要节点。副本将由数据复制策略选择。基本上这是通过在令牌环中顺时针方向进行,从主节点开始,然后根据所需副本的数量停止。
需要注意的是,集群中的每个节点都能够根据上述逻辑识别出负责某个键的节点。每当向集群写入值时,接受请求的节点(协调器节点)将立即知道需要执行写入的节点。
在多个数据中心的情况下,所有 DC 上的所有密钥都将映射到由分区程序确定的完全相同的令牌。 Cassandra 将尝试写入每个 DC 和每个 DC 的副本。