多节点Cassandra集群与客户端读取请求不一致
我有一个运行中的Cassandra集群,里面有两个节点,我通过python-driver API执行一些构建好的CQL查询。我正在对我创建的一系列模型进行单元测试,这些模型主要是为了简化Cassandra API,以便其他开发者使用。当我在单节点集群上测试时,所有的测试都通过了,但在添加了第二个节点后,测试结果就变得非常不稳定,要么失败,要么出错,要么偶尔通过,完全没有规律可言。
我通过比较插入到Cassandra中的对象和从Cassandra查询得到的对象来检查结果,使用的是 self.__dict__ == other.__dict__
,因为我根据从Cassandra收到的列值来填充类的字段。
我认为我找到了问题所在。在我的种子节点上:
cqlsh:mykeyspace> select id,created_at from users;
id | created_at
----+--------------
10 | 139621386780
11 | 139621386780
8 | 139621386780
7 | 139621386780
6 | 139621386780
9 | 139621386780
12 | 139621386780
(7 rows)
在我的第二个节点上:
cqlsh:mykeyspace> select id,created_at from users;
id | created_at
----+--------------
8 | 139621370181
7 | 139621370181
9 | 139621370181
(3 rows)
这里的第一列是一个整数ID,第二列是一个Python的 datetime
对象。我认为发生的情况是,当我向 users
插入一行数据时,这行数据会被插入到第一个或第二个节点上,但当我尝试从Cassandra中检索这个对象时,我可能是从一个不同的节点读取数据,而不是刚刚插入数据的那个节点,因为Cassandra是允许这样做的。然而,如果我设置了 consistency_level=ALL
(我的python CQL调用中确实是这样设置的),难道我不应该收到最新的行数据,而不是之前插入的某一行吗?
更新
请注意,唯一标识符被故意去掉了。
在种子节点上:
$ nodetool status
Datacenter: 243
===============
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Tokens Owns Host ID Rack
UN IP Address 0 136.47 KB 256 100.0% ownsuuid 58
$ nodetool gossipinfo
/IP Address 0
HOST_ID:ownsuuid
SCHEMA:schema
RPC_ADDRESS:0.0.0.0
RELEASE_VERSION:2.0.4
STATUS:NORMAL,-1102599059356328037
SEVERITY:0.0
RACK:58
LOAD:150498.0
DC:243
NET_VERSION:7
/IP Address 1
SCHEMA:schema
HOST_ID:ownsuuid
RPC_ADDRESS:0.0.0.0
RELEASE_VERSION:2.0.4
STATUS:NORMAL,-1102599059356328037
SEVERITY:0.0
RACK:181
LOAD:148937.0
DC:241
NET_VERSION:7
在另一个非种子节点上:
~$ nodetool status
Datacenter: 241
===============
Status=Up/Down
|/ State=Normal/Leaving/Joining/Moving
-- Address Load Tokens Owns Host ID Rack
UN IP Address 1 145.45 KB 256 100.0% ownsuuid 181
$ nodetool gossipinfo
/IP Address 0
STATUS:NORMAL,-1102599059356328037
LOAD:139743.0
RELEASE_VERSION:2.0.4
RACK:58
SCHEMA:schema
SEVERITY:0.0
NET_VERSION:7
HOST_ID:ownsuuid
RPC_ADDRESS:0.0.0.0
DC:243
/IP Address 1
STATUS:NORMAL,-1102599059356328037
LOAD:164405.0
RELEASE_VERSION:2.0.4
RACK:181
NET_VERSION:7
SCHEMA:schema
SEVERITY:0.0
HOST_ID:ownsuuid
RPC_ADDRESS:0.0.0.0
DC:241
1 个回答
听起来你遇到的问题更像是节点之间的沟通问题,而不是其他什么。你知道“nodetool”这个诊断工具吗?它在你Cassandra的bin目录里可以找到。
我在亚马逊的EC2服务器上运行着一个有两个节点的Cassandra集群,我可以在bin目录下运行以下命令:
bash nodetool status
bash nodetool gossipinfo
当你运行这些命令时,应该能看到你所有的节点。这至少能确认你的节点之间能够正常沟通,并且数据能够正确分配。对于我的集群,一旦确认所有节点都能沟通,我可以在任意一个节点上用cqlsh运行查询,并得到100%一致的结果。
另外,你有没有在“conf”文件夹里的cassandra.yaml文件中配置节点的种子值?一旦你的第一个节点启动并运行,第二个节点应该使用第一个节点的IP地址或名称作为它的种子。