cassandra前后端通讯协议,cql(基于v4版本)

native protocol

地址: https://cassandra.apache.org/_/native_protocol.html

cql协议是基于二进制的协议,

首先说明的是,该协议是基于大端对齐的。协议中每一个消息结构首先有一个九个字节标定的消息头,加上后续的消息体组成的,协议所有的消息类型总共包含两种不同类型,包含请求类型与响应类型。

version: 1个字节
flags: 一个字节
stream :2个字节 有符号,最大值32767, 负值保留给event用
opcode : 1个字节
length 四个字节

在这里插入图片描述

version

占一个字节,用于指示版本以及消息的方向(请求还是响应)最高比特位标定了该请求是请求消息还是响应消息,0表示请求消息,1表示响应消息,剩下的比特位标识版本。

  • 请求消息,版本4
    在这里插入图片描述

  • 响应消息 版本4
    在这里插入图片描述

同一条请求链接只会接收一种版本(一般来说是首条报文携带的版本信息,尽管所有的消息都会携带版本信息)

消息头

flags

flags 标志位主要用于标记特殊报文,每种不同的标记都占用不同的比特位

从最低位开始:

  1. 压缩标志
  2. 跟踪标志
  3. 自定义有效负载标志(version4引入的)
  4. 警告标志(version4引入)

具体说明:

  • 0x01:压缩标志。如果设置,那么就表示该帧body中式压缩消息,实际使用压缩效应,应该在startup消息中设置。
  • 0x02: 跟踪标记, 对于一个请求帧,如果设置了,这表示客户端需要跟踪这个请求,需要额外注意的是,跟踪标记只针对 query、prepare和execute,其他的消息类型即使设置了该标记位,也会忽略不计。如果设置了该标记问,那么消息主体会设置一个跟踪id ,即UUID
  • 0x04: 自定义有效负载标志(custom payload flags): 对于请求或者响应帧,表示一个自定义queryhander 的通用键值自定义负载实现存在于框架中(这是啥意思)目前只支持 query\prepate execute batch 请求
  • 0x08:警告标识,由服务器支持,响应帧设置了警告标志,那么正文将包含讲稿文本,警告是一个字符串, 如果没有设置跟踪标记,那么将是消息主体中的第一个值,如果设置了跟踪标记,那么将是uuid后的第一个值。

其余位置当前还没有使用。

stream

这里的stream实际上指的是流id,主要是为了支持服务端的消息异步处理,对于不同的请求流,给定了不同的流id,这样的话,客户端和服务端可以分别处理不同的流,流id必须为正数,最大只能有 32768个不同的流,负值时为event消息准备的。

opcode

操作码

消息类型名
0x00ERROR
0x01STARTUP
0x02READY
0x03AUTHENTICATE
0x05OPTIONS
0x06SUPPORTED
0x07QUERY
0x08RESULT
0x09PREPARE
0x0AEXECUTE
0x0BREGISTER
0x0CEVENT
0x0DBATCH
0x0EAUTH_CHALLENGE
0x0FAUTH_RESPONSE
0x10AUTH_SUCCESS

总共有16种不同的操作码,每种操作码对应分别对应请求与响应消息,如下图所示:

在这里插入图片描述

每种不同的消息类型后续说明

Length

占用四个字节,允许指示的最大长度256MB

值类型

编号类型说明
1int四字节整型
2long八字节整型
3short两字节无符号整型
4string一个short类型的n,后面跟着n个字节的字符
5long string一个int类型的n,后面跟着n个字节的字符
6uuid十六个字节长的uuid
7string list一个short类型的n,后面跟着n个[string]
8bytes一个[int]类型的n, 后面跟着n个字节,如果n<0 则为NULL没有数据
9value一个[int]类型的n, 后面跟着n个字节,-1 指null,-2 指no set 小于-2 则为错误信息
10short bytes一个[short]n, 后面跟着n个byte
11option一对, id是short类型,value取决于支持的值,将在使用的时候定义
12option list一个short 类型的n,后面跟着n个[option]
13inet一个地址(包含ip和端口)一个n(4/16,v4/v6),跟着ip地址,加上一个[int]型端口号
14consistency这是一个[short]类型值,标识一致性级别规范,用于指示多设备间同步等级等内容
15string map短整型的n,后面跟着n对 键值对,键值对都是[string]类型
16string multimap短整型的n后面跟着n对键值对,键是[string]值是[sting list]
17bytes map短整型的n,后面跟着n对键值对,键是[string] 值是[value]

在分布式数据库系统中,尤其是在Cassandra中,[consistency] 字段是用来指定一致性级别(Consistency Level)的。一致性级别决定了对于一个读或写操作,必须有多少副本在操作完成前达成一致。不同的一致性级别在数据的可用性、一致性和容错之间提供了不同的平衡。

  • Cassandra支持多种一致性级别,以下是一些常用的:
  • ANY:只要有一个副本接收了写操作即可。这是最低的一致性级别,它允许在极端条件下丢失数据。
  • ONE:只要有一个副本回复,读或写操作就会成功。
  • TWO 和 THREE:类似于 ONE,但是需要有两个或三个副本回复。
  • QUORUM:超过半数的副本必须回复。对于集群中的N个副本,这意味着至少需要 N/2 + 1个副本。
  • LOCAL_QUORUM:在本地数据中心,超过半数的副本必须回复。
  • EACH_QUORUM:在每个数据中心,至少需要超过半数的副本回复。
  • ALL:所有副本都必须回复。这是最高的一致性级别,但也有可能因为任何单一副本的问题而导致操作失败。

在Cassandra的Native协议中,[consistency] 字段就是用来指定这个一致性级别的。客户端在每次读或写请求时都可以指定它希望的一致性级别。
具体的:

类型
0x0000ANY
0x0001ONE
0x0002TWO
0x0003THREE
0x0004QUORUM
0x0005ALL
0x0006LOCAL_QUORUM
0x0007EACH_QUORUM
0x0008SERIAL
0x0009LOCAL_SERIAL
0x000ALOCAL_ONE

一致性级别的选择取决于应用的需求。如果应用需要高可用性,可以选择较低的一致性级别(如 ONE 或 TWO)。如果应用需要强一致性,可以选择较高的一致性级别(如 QUORUM 或 ALL)。但需要注意的是,选择较高的一致性级别可能会降低系统的可用性和写入吞吐量,因为需要更多的副本参与每个操作。

消息类型说明

请求消息

除了正常的消息响应之外,所有的请求消息都会有错误响应

STARTUP

初始化链接,这种消息类型必须得是第一条消息,一旦链接建立,就不应该再重复发送该条消息。

strartup 的body部分,实际上是一个string map 类型,

在这里插入图片描述

AUTH_RESPONSE

协议中的身份验证基于SASL, 服务器发送身份验证质询,客户端使用这个消息进行应答,直到服务端发送AUTH_SUCCESS.

这个消息的正文时单个byte标记,具体传输的内容是什么取决于认证器,

AUTH_RESPONSE 的响应消息,要么是AUTH_CHALLENGE 消息, AUTH_SUCCESS, 要么就是 ERROR消息。

OPTIONS

该条消息是为了向服务器询问支持的startup消息,这个消息的body部分是空的,服务端应该用SUPPORTED消息回应。

在这里插入图片描述

QUERY

执行CQL查询,这个消息的body部分必须是 <query_parameters>

其中 是表示查询的[long string]

查询参数稍微复杂一点,

<consistency><flags>[<n>[name_1]<value_1>...[name_n]<value_n>][<result_page_size>][<paging_state>][<serial_consistency>][<timestamp>]

首先是consistency字段,用于指示多设备同步等级
然后紧跟着是一个flags,后续参数的多少有flags标签决定,flags直接决定了后续应该还包含什么字段,该字段在不同的版本中还有所不同,版本3,4中 该字段占用一个字节,5版本占用两个字节,并且拓展了几个参数,此处列举的内容以version4为主,version5版本补充内容后续说明

在这里插入图片描述

具体说明:

类型说明
0x01values这是一个具体的数据列表,用于在预处理查询(prepared statements)中填充绑定变量。
0x02skip_metadata标志位用来告诉服务器结果集的元数据(比如列名)不需要在响应消息中返回。这通常在客户端已经知道结果元数据或者进行连续查询时使用,以减少不必要的数据传输。
0x04page_size分页大小用于控制一次读取操作返回的行数上限。这可以帮助管理大量数据的读取,通过分批次的方式读取,而不是一次性加载所有数据。
0x08with_paging_state分页状态用于处理分页查询,它通常包含了从上一次分页读取结束的位置信息,用于开始新的分页读取。
0x10with_serial_consistency对于需要轻量级事务的操作(Lightweight transactions),这个参数指明了在条件更新(如CAS操作)时使用的一致性级别。
0x20with_default_timestamp允许客户端在消息中提供一个默认的时间戳,这个时间戳将被用于操作中的所有写入。
0x40with_name_for_value可以使用命名参数,而不是仅仅按顺序传递参数值。

version 5中增加了两个字段
0x0080 标识,设置了密钥空间
0x0100 如果设置了该bit,那么后面会跟着一个ttl时间,主要用于测试。

query消息将使用result消息响应,具体内容取决于实际需求。

在这里插入图片描述

在这里插入图片描述

PREPARE

准备一个查询,以供以后执行,body部分是一个cql查询,类型是[long string]
服务端将用RESULT消息进行回复。

在这里插入图片描述
在这里插入图片描述

EXECUTE

执行预查询语句,消息body中必须是 <id><query_parameters>

这里的id是query id,是[short bytes]类型,来自于prepare消息的返回值,
query_parameters 参数跟query参数相同。

在这里插入图片描述

BATCH

允许以批处理形式执行查询列表, 正文必须是

<type><n><query_1>...<query_n><consistency><flags>[<serial_consistency>][<timestamp>]
  • type 是一个[bytes] 类型
    type == 0 logged
    type == 1 unlogged
    type == 2 count
  • LOGGED:这是默认类型,也是最安全的一种。在这种模式下,所有的操作被记录到一个批处理日志(batch log)中,然后批量执行。如果在执行过程中任何一个语句失败,批处理日志确保了操作可以重新执行,从而保证数据的原子性和一致性。如果Cassandra无法保证所有语句都成功执行,整个批处理操作将回滚。这种模式对跨分区键的操作是非常重要的,因为它可以提供跨节点的原子性。
  • UNLOGGED:这种类型的批处理不使用批处理日志。因此,如果操作过程中发生故障,那么部分数据可能会被更新,而其他数据则不会。这意味着操作不是原子的,仅适用于对性能有要求且可以容忍部分失败的场景。使用UNLOGGED批处理时,需要应用程序自己处理数据不一致的情况。
  • COUNTER:这种类型的批处理专用于计数器更新。由于计数器的更新不能和其他类型的写操作混合在一个批处理中,因此需要COUNTER类型的批处理来批量更新计数器。计数器批处理是LOGGED的,因为它们使用了批处理日志来保证所有计数器更新操作的原子性和一致性。
  • n 是一个短整型的数字,用来说明后面有多少个查询。

  • query_i: 这里跟着的是需要执行的查询语句,每一个查询语句的形式如下:

    <kind><string_or_id><n>[<name_1>]<value_1>...[<name_n>]<value_n>
    
    • <kind> [byte]类型,只有两种情况,0/1 如果是0 那么后续应该跟着的是[long string]类型的查询语句, 如果是1 那么后续是预处理语句的id
    • <string_or_id> 这个字段取决于前面的kind,string指的是查询语句,id指的是查询id id是[short bytes]类型的
    • <n>: 是[short]类型,标明了后续有多少个value
    • <name_i> 这个字段是对value值得说明,只有flags对应位置设置了才会有, 这里的name是[string]类型
    • <value_i> 这个字段是[value] 类型
  • flags 也是一个[bytes] 类型, 直接影响到了后续的字段数量。这个标签类似于query和execute中的flags, 同样是指定的几个bit位去指定了后面还有多少字段

类型说明
0x10with serial consistency用于设置串行一致性原则,这种情况下只能设置两种 SERIAL或者LOCAL_SERIAL, 如果没有设置,则默认是SERIAL
0x20with default timestamp设置默认时间戳
0x40with name for values设置值的名称,如果设置了这个标志位,那么所有的query_n 前面都必须有一个string类型的name

这个消息得响应为 RESULT消息。

在这里插入图片描述

REGISTER

注册此链接以接收某些类型得事件,该消息类型为[string list]

该消息的响应消息为 READY消息。

在这里插入图片描述

响应消息

ERROR

指示处理请求时的错误,这里的错误是一个[int]类型的错误码 后面跟着一个[sting] 类型的错误信息。

READY

指示服务器已经准备好处理查询,如果没有碱性身份验证,则在startup消息之后由服务器发送。
该消息的body部分是空的

在这里插入图片描述

AUTHENTICATE

指示服务器需要身份验证,以及那个身份验证机制来使用

身份验证是基于SASL机制。正文是[string]类型

SUPPORTED

指示服务器支持哪些启动选项,该消息是作为opting的响应

body 部分是[string multimap] 消息类型,

在这里插入图片描述

RESULT

是对QUERY、PREPARE、EXECUTE或者BATCH 消息的响应

RESULT消息正文的第一个元素是[int] 表示结果的种类,body的其余部分由第一个元素决定的。

类型说明
0x0001void没有信息的结果
0x0002Rows用于选择查询结果,返回一组行
0x0003set_keyspace返回一个use 查询结果
0x0004prepared结果到prepare消息
0x0005scheme change模式更改查询的结果
void


在这里插入图片描述

Rows

表示一组行, 行结果的其余部分结构为

 <metadata><rows_count><rows_content>
  • metadata 的组成结构为

    <flags><columns_count>[<paging_state>][<global_table_spec>?<col_spec_1>...<col_spec_n>]
    
    • flags
      flags 是[int] 类型, flags的值影响到该部分后续部分的内容。每一个bit位代表着不同的意思
    类型说明
    0x0001Globle table spec如果设置了,那么只有一个表规范(keyspace和表名)
    0x0002has more pages显示是不是最后一部分数据
    0x0004no metadata没有更多的信息显示
    • columns_count : [int]类型,表示后面有多少行数据
    • globle table spec : 全局的一个表详情,主要包括keyspace,和所属的 表名(都是[string]类型的。
    • col spec i: 指定查询中的列, 基本组成
       (<ksname><tablename>)?<name><type>
    

    首先是ksname 和tablename 两个[string]类型的字段,这两个字段仅仅用户flags没有设置globle table spec 时。name是 [string]类型,type是[option]类型。这里主要是为了指示每一个列的结构,如果是用户自定义的列,则使用的是UDT结构,具体结构参考如下引用:

      0x0000    Custom: the value is a [string], see above.
      0x0001    Ascii
      0x0002    Bigint
      0x0003    Blob
      0x0004    Boolean
      0x0005    Counter
      0x0006    Decimal
      0x0007    Double
      0x0008    Float
      0x0009    Int
      0x000B    Timestamp
      0x000C    Uuid
      0x000D    Varchar
      0x000E    Varint
      0x000F    Timeuuid
      0x0010    Inet
      0x0011    Date
      0x0012    Time
      0x0013    Smallint
      0x0014    Tinyint
      0x0020    List: the value is an [option], representing the type
                      of the elements of the list.
      0x0021    Map: the value is two [option], representing the types of the
                     keys and values of the map
      0x0022    Set: the value is an [option], representing the type
                      of the elements of the set
      0x0030    UDT: the value is <ks><udt_name><n><name_1><type_1>...<name_n><type_n>
                     where:
                        - <ks> is a [string] representing the keyspace name this
                          UDT is part of.
                        - <udt_name> is a [string] representing the UDT name.
                        - <n> is a [short] representing the number of fields of
                          the UDT, and thus the number of <name_i><type_i> pairs
                          following
                        - <name_i> is a [string] representing the name of the
                          i_th field of the UDT.
                        - <type_i> is an [option] representing the type of the
                          i_th field of the UDT.
      0x0031    Tuple: the value is <n><type_1>...<type_n> where <n> is a [short]
                       representing the number of values in the type, and <type_i>
                       are [option] representing the type of the i_th component
                       of the tuple
  • rows_count:这是一个[int]型数据,指示后面有多少个row文本数据。
  • row_content: 这个结构的组成结构为 <row_1> <row_2>...<row_i>...<row_n>, 每一个 row 的组成结构都是 <value_1><value_2>...<value_i>...<value_n> 需要说明的是 row 数量由row_count决定,value数量由column_count 决定。

在这里插入图片描述

set keyspace

后面跟着一个[string]类型,指明了一个被设置keyspace 的名称

在这里插入图片描述

prepared

parepare消息的响应消息。消息结构是:

<id><medadata><result_metadata>
  • id 是[short bytes] : 返回一个请求id
  • metadata 组成结构:
	<flags><columns_count><pk_count>[<pk_index_1>...<pk_index_n>][<global_table_spec>?<col_spec_1>...<col_spec_n>]

这里的metadata的定义跟前面定义类似,具体的字段意义有所不同,这里不做详细说明。

  • result_metadata
    该字段定义与前者相同

在result结果中,kind为4是,是为了处理预处理语句,这里定义了两个不同的结构,一个是metadata,一个是result_metadata ,为什么要设置这两个结构,这两个结构有着什么相同与不同

  • 在数据库协议中,特别是当涉及预处理(prepared)语句时,kind 值为 4 表示该结果是一个 prepared 语句的结果。预处理语句是一种数据库优化技术,它允许将一个查询模板先发送到数据库服务器进行编译和优化,然后可以多次执行而不需要重新编译,只需传递不同的参数即可。

在这种情况下,由于预处理的语句可能在不同的上下文中被重复执行,返回的结果集可能会因为传递的参数不同而有所不同。因此,协议中会有 metadataresult_metadata 两个不同的结构来描述不同阶段的元数据信息。

  1. metadata: 这个部分描述了预处理语句本身的结构,包括预处理语句的参数。它定义了每个参数的类型和(如果适用的话)位置。这样,客户端知道如何构造后续执行该预处理语句时需要传递的参数值。

  2. result_metadata: 这个部分描述了执行预处理语句后返回的结果集的结构,包括列的名称、类型和其他可能的描述信息。每次执行预处理语句时,它都会返回与 result_metadata 对应的数据。

两个结构的相同之处在于,它们都用来描述数据的结构,但它们描述的内容不同:

  • metadata 关注于如何正确地发送参数到预处理语句。
  • result_metadata 关注于如何解释执行预处理语句后获得的结果集。

这样的设计允许客户端软件在准备语句时了解如何发送参数,并在执行时了解如何解析返回的数据。这种分离也意味着预处理的结果可能与原始查询在元数据方面略有不同,特别是如果预处理语句允许返回不同的结果集的话(例如,根据传入的参数,可能有不同的列被包含在结果中)。

在这里插入图片描述

schema_change

该类型是为了响应schema altering query ,body部分为 <change_type><target><options>, 具体定义参考event消息

EVENT

服务端推送的事件,客户端只会接受已经注册的事件,EVENT的消息的正文,使用[string] 消息进行发送,消息的剩余部分取决于事件类型

  1. 拓扑变化,后面跟着[string]和[inet] 分别对应更改类型,增加/删除节点,后面跟着新的/删除的节点
  2. 状态变化,后面跟着[string]和[inet] 组成,分别对应于更改类型up/down,
  3. schema change : <change_type><target><options>
    • changetype :[string] 涉及的更改,创建,更新,删除,
    • target : 更改的对象,keyspace , table, type,function, aggregate
    • options,: 这个跟target相关,如果是key space 那么是一个[string] ,如果是table,type ,那么是两个[string], 第一个是keyspce 名,第二个是对应对象的名称,如果是另外两个,则需要增加 [string list]

所有的event的流id都是-1

在这里插入图片描述

AUTH_CHALLENGE

服务器身份质询,body 是单个[bytes] 标记

AUTH_SUCCESS

验证成功

  • 15
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

望晓天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值