关于Cassandra BLOCKING read repair阻塞副本写入及破坏原子性的疑问
Cassandra Read Repair 相关疑问解答
一、BLOCKING Read Repair 阻塞逻辑疑问
官方对BLOCKING read repair的说明如下:
如果触发了read repair,读取操作会阻塞发往其他副本的写入请求,直到写入满足consistency level要求。
针对两个疑问的解释:
- 为什么read repair需要阻塞其他写入?
这里的“阻塞”并非拦截集群所有对对应副本的写入请求,仅指当前读操作触发的修复流程中,协调器会等待本次修复写入的确认达到一致性级别要求后,才会返回读结果给客户端。在此期间,和本次读取涉及的相同数据的并发写入会在协调器端排队,避免修复写入和正常写入交叉执行,导致读返回给客户端的结果,和最终副本持久化的结果不一致,保证读操作符合指定的一致性级别要求。 - read repair如何能够阻塞其他副本上的写入?
阻塞动作实际发生在协调器节点,而非直接管控副本节点的写入权限。协调器会为每个读取请求涉及的分区+数据行生成临时的调度标识,同一时间针对相同数据的读修复、写入请求会被串行处理:读修复先拿到执行权时,后续同数据的写入请求会在协调器侧暂存排队,等读修复的写入确认满足CL要求后,再处理排队的写入。副本节点本身不会被读修复锁定,仅同一协调器调度的相关请求会被串行执行。
二、BLOCKING Read Repair 破坏单分区写入原子性疑问
官方对该问题的说明如下:
Cassandra尝试提供partition level write atomicity,但由于read repair仅修复SELECT语句覆盖的数据,当读取粒度比写入粒度更细时,read repair会破坏write atomicity。例如:你通过batch操作向一个clustered partition写入多行数据,之后通过指定clustering column的SELECT语句查询单行数据时,read repair就可能破坏write atomicity。
针对两个疑问的解释:
- 为什么单分区batch的原子性会被read repair破坏?
单分区batch的原子性保证是:batch内的所有写入要么对读请求全部可见,要么全部不可见,该保证的前提是所有batch内的数据会作为一个整体,在副本端原子写入。但read repair的修复粒度完全匹配SELECT语句的查询范围:假设你通过单分区batch写入了同一个分区下clustering key为1、2、3的三行,该batch在某一个副本上写入完全失败,三行都未持久化。此时你发起了一个仅查询ck=1的SELECT请求,触发read repair后,修复逻辑只会把ck=1这一行同步到写入失败的副本上,不会同步剩下的ck=2、3行。这时候该副本上就只存在ck=1的行,后续如果有读请求命中该副本查询全分区数据,就会看到batch仅写入了一半数据,原子性就被破坏了。 - 原子性破坏对开发者的实际影响:
- 如果你依赖单分区batch的原子性做业务逻辑判断,比如batch写入的多行是同一个订单的关联条目,要求要么全部展示要么全部不展示,可能出现用户仅看到部分条目的异常。
- 做数据统计时会出现结果不一致,比如统计某分区下的行数,不同时间发起的读请求可能返回不同的计数,直到后台常规反熵修复同步完剩余的缺失行。
- 如果你业务上有“写入单分区batch后,读单条数据判断batch是否写入成功”的逻辑,可能出现判断为成功,但后续读取全量数据时缺失其他关联行的问题。
内容的提问来源于stack exchange,提问作者CKK
相关产品推荐
相关产品推荐

