question

bonian.hu_177317 avatar image
bonian.hu_177317 asked Erick Ramirez edited

如果写入不符合一致性级别,Cassandra会采取纠正措施吗?

如果写入数据时,部分节点写入成功,但是不符合一致性级别。Cassandra会自动对写入成功的节点采取补偿措施吗?

consistency level
10 |1000

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

1 Answer

bonian.hu_177317 avatar image
bonian.hu_177317 answered 18701326550z_188064 commented

Cassandra 写入时可能会出现一下几种情况:

  • 如果Coordinator(协调者)没有检测到足够的 Replica (副本) 满足一致性,Cassandra会返回一个Unavailable Exception(无法达成异常 ) ,同时不会写入任何数据。


  • 如果Cassandra有足够的Replica但是写入的请求响应没有在一定时间内的到回复, Coordinator会返回一个Timeout Exception(超时的异常).


  • 如果有足够的Replica且满足一致性。 但是一些Replica不可用(宕机或者无法得到响应), Coordinator 会在其它节点上储存一个hint (类似于备份)。 当这些副本节点重新上线时,Coordinator 会将hint自动重新写入这些 Replica,最终完成整个的写入过程. 这个过程称之为 hinted-handoff (提示移交).
6 comments Share
10 |1000

Up to 8 attachments (including images) can be used with a maximum of 1.0 MiB each and 10.0 MiB total.

18701326550z_188064 avatar image 18701326550z_188064 commented ·

返回TimeOut Exception异常后,写入成功的数据有处理措施吗?,

0 Likes 0 ·
weideng_84207 avatar image weideng_84207 18701326550z_188064 commented ·

Cassandra的写是没有回滚(rollback)机制的。如果发生了Timeout Exception,导致客户端写入失败,一般情况下客户端(或者下层的driver)会采用Retry重传的机制,来保证这笔写入最终是会成功的。


Cassandra表里存放的数据(除了Counter计数器类型的数据)都是幂等的(idempotent),写入多次同样的数据不会影响读取数据的准确性。理解幂等这个在分布式数据库领域里关键的概念,并且知道怎样使用幂等的数据模型,对用好Cassandra很重要。

2 Likes 2 ·
18701326550z_188064 avatar image 18701326550z_188064 weideng_84207 commented ·

谢谢,讲的很有道理。请问对于Counter这种非幂等的操作,如果失败报错后,应该怎么处理呢?不能直接重试吧。

0 Likes 0 ·
Tonny avatar image Tonny commented ·
  • 如果有足够的Replica且满足一致性。 但是一些Replica不可用(宕机或者无法得到响应), Coordinator 会在其它节点上储存一个hint (类似于备份)。 当这些副本节点重新上线时,Coordinator 会将hint自动重新写入这些 Replica,最终完成整个的写入过程. 这个过程称之为 hinted-handoff (提示移交).

这里面的无法得到响应的节点,存在一种情况:比如gossip检测正常,写请求刚刚发过去就宕机,这时候不会在coordinator上写入给这个宕机节点的hint数据吧,只能等节点拉起进行repair手动修复,我的理解对吗?



0 Likes 0 ·
weideng_84207 avatar image weideng_84207 Tonny commented ·
这里面的无法得到响应的节点,存在一种情况:比如gossip检测正常,写请求刚刚发过去就宕机,这时候不会在coordinator上写入给这个宕机节点的hint数据吧,只能等节点拉起进行repair手动修复,我的理解对吗?

这个理解不正确。Coordinator决定要不要存储hint,有两个触发原因:

1. (通过Gossip的信息Coordinator已经知道了)所有的副本节点中有没有离线节点,如果有,但是一致性级别仍然能够满足,那么写操作会继续,但是对应于每个离线节点,都会有一份hint保存在Coordinator上;当然,如果一致性级别已经没法满足了,那这个写操作会由Coordinator直接向客户端报错,没有hint产生。

2. 如果Coordinator没有发现离线节点,决定继续写入,但是因为种种原因(可能是因为Coordinator刚刚决定写入,就有副本节点宕机了;也有可能是因为某些副本节点出现临时的GC导致响应超时)副本节点不能在timeout发生之前确认写入成功,那对于每一个不能成功在timeout之前ACK(确认写入成功)的副本,Coordinator都会存储一份hint。


2 Likes 2 ·
Tonny avatar image Tonny weideng_84207 commented ·

okok.找到代码了,应该是下面这个逻辑做的你说的第2种情况了(也就是只要coordinator把请求发出去,只要没有在timeout之前收到写入成功的响应<包含失败>,他都会存储一份hint了),非常感谢

2 Likes 2 ·
write-hint.png (58.7 KiB)