深入解析cassandra 轻量级事务原理

本文涉及的产品
云解析DNS-重点域名监控,免费拨测 20万次(价值200元)
简介: how to usecassandra是一个无主架构,多个node可以并行写,但并发场景下对于先读后写的操作,数据会有正确性问题。从cassandra2 开始提供轻量级事务支持,用于cas更新。使用示例:cqlsh> UPDATE cycling.cyclist_name SET firstname = ‘Roxane’ WHERE id = 4647f6d3-7bd2-4085-8d6c-1229351b5498 IF firstname = ‘Roxxane’;这其实是一个标准的compare and swap 示例。

how to use

cassandra是一个无主架构,多个node可以并行写,但并发场景下对于先读后写的操作,数据会有正确性问题。从cassandra2 开始提供轻量级事务支持,用于cas更新。使用示例:

cqlsh> UPDATE cycling.cyclist_name
  SET firstname = ‘Roxane’
  WHERE id = 4647f6d3-7bd2-4085-8d6c-1229351b5498
  IF firstname = ‘Roxxane’;

这其实是一个标准的compare and swap 示例。接下来我们深入看看cassandra是如何实现的,其实我们可以发现,其实它既没有事务,也不轻量级。

理论基础

cassandra轻量级事务是通过basic-paxos协议实现的,提供线性化一致性保证,具体的理论基础可以参考paxos made simple。建议读者先深入理解该论文。
论文讲述得出一个值,主要有两个阶段prepair+accept,大体流程见下图:
image

Cassandra LightWeight Transaction paxos实现在原来的二阶段perpair, propose/accept上增加了commit阶段,论文中对于如何 Learning a Chosen Value的描述,工程化实现不太靠谱,常见的做法如下:

一个提案是否被chosen,acceptor是不知道的,只有proposer知道是否满足多数派,如果满足了,增加commit阶段,在该阶段,把已经chosen的提案提告知learner,learner更新自身状态机。

cassandra 实现

工程实现跟理论还是有些gap的,basic paxos最大的问题是只是用来表决出一个值,但cassandra cas需要持续写入多轮(论文中instance)值,cassandra是在prepare阶段,发现上一轮已经正常commit了,即可开始下一轮,提议新的值。
cassandra使用basic paxos本质上为所有的cas请求申请槽位(slot),保证所有请求线性一致性,不会出现replica A执行了op1->op2,而replica B执行了op2->op1这种不一致的结果。

变量介绍

  • ballot: 提案号,proposer保证线性单调增长,在c*里面使用时间戳表示。
    每个node(acceptor)都有如下三个本地变量:
  • in_progress_ballot: prepair 阶段proposer提案号,acceptor 发现只要比自己本地的大,会promise然后更新该本地变量,简称为promised ballot,代码中使用in_progress_ballot保存
  • proposal_ballot: propose阶段,proposer提案号,如果比acceptor已经promise的ballot(上述in_progress_ballot)大的话,acceptor会accept该提案,并把提案中的value持久化。
  • most_recent_commit_at: proposer提案被多数派acceptor接受后,该value被chosen,proposer向learner发送commit消息,commit消息无论如何都会被接受,持久化到磁盘上,most_recent_commit_at是这个决议commit时间。有时简称为commit ballot

实现流程

image

共四个阶段

  1. Prepare/Promise
  2. 产生一个ballot,向replica 发送prepare请求,replica答应不会接受旧的ballot更新,并且告知最后accept 提案及最近commit提案。
  • 如果最后accept提案比最近commit提案新,说明该accept提案还没有走完整个流程,也许后端节点故障导致的。coordinate重新发起propose+commit请求,跳至步骤3,4,结束上轮未完提案后,可开始本轮自己的新提案
  • 如果最近commit提案都比accept提案新, 说明没有还处于流程中的提案,可直接开始本轮自己的新提案。
  1. Read/Results
  • 从replica读取数据,一致性级别为Quorum或者Local_Quorum
  • 读取完判断是否满足condition条件,将上述cql更新变成mutation, 作为提案的值,进入下面的propose/accept阶段。
  1. Propose/Accept
  • 向所有replica发送propose 提案,proposal_ballot必须比replica本地in_progress_ballot高,高的话,给cordinate回复
  1. ack,并持久化在system.paxos表,否则说明replica本地in_progress_ballot更高,代表其他cordinate发送了更新的prepare提案,给当前cordinate回复reject ack。
  2. Commit/Acknowledge
    如果多数派replica接受了这个提案,我们进入commit,像learner(cassandra中的replica)发起commit请求
  • cordinate向所有replica发送一条commit消息,消息包含ballot&value
  • 因为前面2步的关系,这一定是最高的可见的commit ballot,后续新的paxos阶段promise响应也会回复此新值。
    commit阶段首先相应的表(columnFamily)会apply 这条mutation,然后做清理, 会将proposal_ballot,及proposal value置空,标识本轮paxos正常结束。

详细代码请阅读StorageProxy.cas()

LightWeight Transaction 问题

轻量级事务是比较费的,由上面的流程可以看出,正常流程需要4次 RTT,如果发生“活锁”冲突,多个cordinator同时改同一partitionKey,propose 提案会不断被reject,c* 的解决办法是随机睡眠一段时间重试,但带来的问题是线程并发度越高,竞争越激烈,写失败概率越大,分位延时越大。下图99分位写延时能到200ms以上,社区也是不太建议大面积广泛使用cas。
image

摘自:https://www.slideshare.net/DataStax/light-weight-transactions-under-stress-christopher-batey-the-last-pickle-cassandra-summit-2016

但作为数据库,read-before-write是业务系统非常常见的需求,cassandra只能原子写,给我们使用带来很多不便。对于cas性能短板,那么如何改进呢?业界常见的有这么些做法

  • leader模式:如raft,multi-paxos,先选出唯一主,不会有提案的contention,每个写请求都是phase2 accept请求,commit可以异步,这样大大降低了4轮的rpc,可缩减到一跳rpc
  • leaderless模式,改进的paxos,如epaxos,无主跟cassandra相性更兼容,社区后续改进思路就是讲basic-paxos实现改为epaxos,下面我们将花些时间了解一下epaxos

社区改进方向及进展

CASSANDRA-6246, 社区打算使用epaxos做cas优化,将在4.x合入,但该ISSUE已经open了数年,预期进展不会太过乐观,读者了解epaxos原理后,可自行实现改进。
epaxos论文:Egalitarian Paxos

Epaxos介绍

EPaxos用到的几个概念

在描述前,先描述几个概念。

在EPaxos中,每一个command γ都附带attribute,其中包括deps和seq。deps记录了跟γ冲突的command的instance id,γ依赖这些instance id对应的command。deps中维护的依赖关系就是定序用的关系,γ要排在deps中 的command后面。seq是一个序列号,用来在execution阶段打破循环依赖。

接收client请求的副本称之为这个command γ的command leader,记作Lγ。每个副本都会持久化记录到cmds中,通过Q.i这种instance id来索引并读写。

协议分成两个部分,首先是正常处理客户端请求的处理过程,这个过程包括三个阶段:(1) Phase1 Establish ordering constraints (2) Paxos-Accept Phase (3) Commit Phase。其中一个命令可能走Phase1 + Paxos-Accept Phase + Commit Phase,或者Phase 1 + Commit Phase,前者称之为slow path,后者称之为fast path。

需要提前指明的是,优化EPaxos采用的是thrifty模式,fast quorum是 F'=F+⌊(F+1)/2⌋,其中F为系统容忍的少数派,command leader向 F' 个副本发送pre-accept请求,而不是向 2F+1 个副本发送请求等待 F'个回应。

协议详细介绍

image

恢复阶段Explicit Prepare

副本Q怀疑L失效,尝试去恢复L.i这个instance。

  • 递增ballot number:设Q知道的最大proposal id是epoch.b.Q,则使用新的proposal id epoch.(b+1).Q
  • 向所有副本(包括自己)发送Prepare(epoch.(b+1).Q),等待至少多数派的回应。
  • 假设所有回应中最大ballot number的是ballotmax,定义R是所有回应中ballot number等于ballotmax的响应的集合。
  • 如果R没有关于这个instance id的任何信息,那么推出恢复阶段,副本Q对L.i实例尝试去commit no-op。
  • 如果R中包含了至少一条(γ,seqγ,depsγ,committed),则对L.i实例(γ,seqγ,depsγ)执行Commit Phase。
  • 如果R中包含了至少一条(γ,seqγ,depsγ,accept),则对L.i实例(γ,seqγ,depsγ)执行Paxos-Accept Phase。
  • 如果至少(F+1)/2个副本回应了pre-accept,并且它们回应的seqγ,depsγ都与L.i的epoch.0.b那轮PreAccept请求中记录相同,那么就进入TryPreAccept阶段,否则就回到slow path重新来一遍commit。

TryPreAccept阶段

副本Q发送TryPreAccept(L.i,γ,depsγ,seqγ)给中未回应过pre-accept response的副本。

  • 副本R收到TryPreAccept(L.i,γ,depsγ,seqγ)之后,如果R现在记录了command δ,同时满足如下三个条件:

    • γ~δ
    • γ∉depsδ
    • δ∉depsγ 或者 δ∈depsγandseqδ≤seqγ
      就回应NACK,并带上冲突command的一些信息(包括δ的instance id、command leader、instance的状态如pre-accepted/accepted/committed),否则就回应ACK。
  • 副本Q在收到TryPreAccept的响应之后,顺序进行如下的条件判断:
  • 如果pre-accepted的副本数目已经大于等于F+1,则Q退出恢复过程,开始对L.i实例γ,depsγ,seqγ 执行Paxos-Accept阶段。
  • 如果某个TryPreAccept NACK中反馈了存在一个已经committed的冲突command,则退出恢复阶段,从头开始slow path来在L.i实例上重新尝试提交γ。
  • 如果某个TryPreAccept NACK中反馈了一个实例δ,其中δ∉depsγ并且Lγ∈γ,则退出恢复阶段,从头开始slow path来在L.i实例上重新尝试提交γ。
  • 如果存在command γ0,Q是先尝试恢复γ0,但因为发现可能需要先恢复跟γ0冲突的γ。在这种情况下,如果发现γ0的command leader是γ的fast quorum中的一个,那么就退出γ的恢复,从头开始slow path来重新提交γ。
  • 如果前面的条件都不满足,Q就推迟defer γ的恢复,先恢复与γ冲突的某个command。

## 优点

  • leaderless,负载更均衡,对于raft,multi-paxos存在leader的bottleneck,epaxos不存在这个问题
    无主模式还有一个非常大的优点,延时更稳定,集中式主模式往往因为主宕机,从需要抢主,重新提供服务,导致延时陡增,像epaxos,每轮消息任何副本都可以当主,挂了一台无所谓,延时稳定,更适合在线服务。
  • 延时优化,无冲突情况下,能优化当前cas实现 4轮rpc至2轮rpc,preAcept+commit,commit还可以异步发送,不同步等ack。
    就算较之于论文basic-paxos(3轮rpc)也是路径较优,当然略逊于raft/multi-paxos,毕竟一轮rpc。
  • 缺点:epaxos比paxos复杂多了,不过好在于作者提供了go实现的原型,见代码库
    https://github.com/efficient/epaxos

    • 延时肯定是比multi-paxos强主模式差的

性能

参考论文第12页,需要指出的是epaxos延时跟multi-paxos对比,作者尽挑对自己有利的说,需要明确指出同机房下epaxos延时比paxos差的,比如在CA地域。

参考

paxos made simple
Egalitarian Paxos
EPaxos协议解读

相关文章
|
10月前
|
安全 算法 网络协议
解析:HTTPS通过SSL/TLS证书加密的原理与逻辑
HTTPS通过SSL/TLS证书加密,结合对称与非对称加密及数字证书验证实现安全通信。首先,服务器发送含公钥的数字证书,客户端验证其合法性后生成随机数并用公钥加密发送给服务器,双方据此生成相同的对称密钥。后续通信使用对称加密确保高效性和安全性。同时,数字证书验证服务器身份,防止中间人攻击;哈希算法和数字签名确保数据完整性,防止篡改。整个流程保障了身份认证、数据加密和完整性保护。
|
9月前
|
机器学习/深度学习 数据可视化 PyTorch
深入解析图神经网络注意力机制:数学原理与可视化实现
本文深入解析了图神经网络(GNNs)中自注意力机制的内部运作原理,通过可视化和数学推导揭示其工作机制。文章采用“位置-转移图”概念框架,并使用NumPy实现代码示例,逐步拆解自注意力层的计算过程。文中详细展示了从节点特征矩阵、邻接矩阵到生成注意力权重的具体步骤,并通过四个类(GAL1至GAL4)模拟了整个计算流程。最终,结合实际PyTorch Geometric库中的代码,对比分析了核心逻辑,为理解GNN自注意力机制提供了清晰的学习路径。
647 7
深入解析图神经网络注意力机制:数学原理与可视化实现
|
10月前
|
机器学习/深度学习 算法 数据挖掘
解析静态代理IP改善游戏体验的原理
静态代理IP通过提高网络稳定性和降低延迟,优化游戏体验。具体表现在加快游戏网络速度、实时玩家数据分析、优化游戏设计、简化更新流程、维护网络稳定性、提高连接可靠性、支持地区特性及提升访问速度等方面,确保更流畅、高效的游戏体验。
244 22
解析静态代理IP改善游戏体验的原理
|
9月前
|
机器学习/深度学习 缓存 自然语言处理
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
Tiktokenizer 是一款现代分词工具,旨在高效、智能地将文本转换为机器可处理的离散单元(token)。它不仅超越了传统的空格分割和正则表达式匹配方法,还结合了上下文感知能力,适应复杂语言结构。Tiktokenizer 的核心特性包括自适应 token 分割、高效编码能力和出色的可扩展性,使其适用于从聊天机器人到大规模文本分析等多种应用场景。通过模块化设计,Tiktokenizer 确保了代码的可重用性和维护性,并在分词精度、处理效率和灵活性方面表现出色。此外,它支持多语言处理、表情符号识别和领域特定文本处理,能够应对各种复杂的文本输入需求。
1139 6
深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
|
10月前
|
编解码 缓存 Prometheus
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
本期内容为「ximagine」频道《显示器测试流程》的规范及标准,我们主要使用Calman、DisplayCAL、i1Profiler等软件及CA410、Spyder X、i1Pro 2等设备,是我们目前制作内容数据的重要来源,我们深知所做的仍是比较表面的活儿,和工程师、科研人员相比有着不小的差距,测试并不复杂,但是相当繁琐,收集整理测试无不花费大量时间精力,内容不完善或者有错误的地方,希望大佬指出我们好改进!
666 16
「ximagine」业余爱好者的非专业显示器测试流程规范,同时也是本账号输出内容的数据来源!如何测试显示器?荒岛整理总结出多种测试方法和注意事项,以及粗浅的原理解析!
|
9月前
|
传感器 人工智能 监控
反向寻车系统怎么做?基本原理与系统组成解析
本文通过反向寻车系统的核心组成部分与技术分析,阐述反向寻车系统的工作原理,适用于适用于商场停车场、医院停车场及火车站停车场等。如需获取智慧停车场反向寻车技术方案前往文章最下方获取,如有项目合作及技术交流欢迎私信作者。
685 2
|
11月前
|
机器学习/深度学习 自然语言处理 搜索推荐
自注意力机制全解析:从原理到计算细节,一文尽览!
自注意力机制(Self-Attention)最早可追溯至20世纪70年代的神经网络研究,但直到2017年Google Brain团队提出Transformer架构后才广泛应用于深度学习。它通过计算序列内部元素间的相关性,捕捉复杂依赖关系,并支持并行化训练,显著提升了处理长文本和序列数据的能力。相比传统的RNN、LSTM和GRU,自注意力机制在自然语言处理(NLP)、计算机视觉、语音识别及推荐系统等领域展现出卓越性能。其核心步骤包括生成查询(Q)、键(K)和值(V)向量,计算缩放点积注意力得分,应用Softmax归一化,以及加权求和生成输出。自注意力机制提高了模型的表达能力,带来了更精准的服务。
12461 46
|
10月前
|
Java 数据库 开发者
详细介绍SpringBoot启动流程及配置类解析原理
通过对 Spring Boot 启动流程及配置类解析原理的深入分析,我们可以看到 Spring Boot 在启动时的灵活性和可扩展性。理解这些机制不仅有助于开发者更好地使用 Spring Boot 进行应用开发,还能够在面对问题时,迅速定位和解决问题。希望本文能为您在 Spring Boot 开发过程中提供有效的指导和帮助。
1225 12
|
10月前
|
开发框架 监控 JavaScript
解锁鸿蒙装饰器:应用、原理与优势全解析
ArkTS提供了多维度的状态管理机制。在UI开发框架中,与UI相关联的数据可以在组件内使用,也可以在不同组件层级间传递,比如父子组件之间、爷孙组件之间,还可以在应用全局范围内传递或跨设备传递。
300 2
|
9月前
|
负载均衡 JavaScript 前端开发
分片上传技术全解析:原理、优势与应用(含简单实现源码)
分片上传通过将大文件分割成多个小的片段或块,然后并行或顺序地上传这些片段,从而提高上传效率和可靠性,特别适用于大文件的上传场景,尤其是在网络环境不佳时,分片上传能有效提高上传体验。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

推荐镜像

更多
  • DNS