写在前面
纸上得来终觉浅,绝知此事要躬行。
想起来上学时候老师的教导,再好用的脑瓜,也不如烂笔头。励志后面养成记笔记的习惯。
本文是Vitess设计文档:https://github.com/vitessio/vitess/blob/master/doc/LifeOfAQuery.md 的译文,有任何理解不对的地方欢迎指正。
概述
在vitess中执行一次Query会涉及到Client Application,VtGate,VtTablet和MySQL实例。本文就对Query执行过程中,这四个组件的交互细节进行说明。
从宏观来看,如上图所示:首先client端向VtGate发送一个Query。VtGate解析该Query,然后将本次Query路由到正确的VtTablets上。接收到Query的每个VtTablet都会做相应的验证并且将Query发送给下面的MySQL实例。在从MySQL上收集完相应的结果之后,VtTablet会将结果发送给VtGate。一旦VtGate从所有的VtTablets上收集完了所有的查询结果之后,VtGate会将这些查询结果合并,并返回给Client端。 当某一个或者多个VtTablet发生错误的时候,若这些错误是可恢复的,VtGate将会发起重试。只有这些错误时不可恢复的或者达到了最大重试次数,VtGate才会认为本次Query失败。
从Client到VtGate
Client向VtGate上发送一次RPC请求,在这次RPC请求中嵌入了相应的SQL语句,VtGate上的RPC Server对本次请求进行unmarshal,调用VtGate上相应的方法,并将本次查询的结果语句返回给Client。
VtGate会维护一个内存表来存放每个service可用的rpc方法,例如:VtGate使用“VTGate”表示它的服务名并且在 [go/vt/vtgate/vtgate.go] (https://github.com/vitessio/vitess/blob/master/go/vt/vtgate/vtgate.go) 中定义的大部分的方法都被用来服务于"VTGate"接收的RPC请求。
从 VtGate 到 VtTablet
VtGate收到一次RPC调用之后,它提供的众多Execute* 方法中的一个会被调用,VtGate需要指出哪些Shard将会收到Query,并且会向这些Shard中的每一个都发从该Query。另外,VtGate会与Topo Server进行通讯获得必要的信息从而为每个Shard都创建一个VtTablet连接。到这里,VtGate可以并行的向正确的VtTablets上发送Query。在超时或者VtTablet上返回可恢复的错误时,VtGate也会发起重试。
在VtGate内部,有一个ScatterConn 实例并且使用ScatterConn 来执行跨多个ShardConn(每个ShardConn对应一个Shard)的连接的查询。 ScatterConn在选择的多个Shard上并行的执行Query。ScatterConn首先为每个shard获得一个ShardConn,并且通过ShardConn的Execute方法发送Query。当启用了2PC的时候,VtGate上对于Query的处理过程如下:VtGate会在每个Connection上请求一个session,若请求的session已经处于一个Transaction中了,将会在该connection上开启一个新的transaction,并且使用新的transaction id来更新该session。若该session已经包含了一个针对于该shard的transction id,就重用该transaction id。若在事务执行期间任意的一个shard返回了不可恢复的请求,VtGate将会在所有的Shard上执行事务回滚。
一个ShardConn对象代表了一个负载均衡的连接(后面是一组VtTablets,这些VtTablets属于同一个shard)。ShardConn 对象可以在过个goroutines之间被并发的使用,而且是协程安全的。
从VtTablet 到 MySQL
一旦VtTablet收到了从VtGate发送过来的rpc请求后,VtTablet在将Query发送给MySQL之前会做一些check。首先,VtTablet会验证当前VtTablet的状态(包括session id), 然后会生成query plan并且会应用预定义好的查询规则而且会进行ACL 验证。VtTablet还会检查该查询是否会产生Row Cache命中,若在Row Cache中命中了,则会立即返回结果数据。除此之外, VtTablet会将同时执行的重复查询进行归一,只执行其中的一个Query,然后在多个同时执行的Query之间共享该Query产生的结果。若既没有row cache命中,各个验证条件也通过,VtTablet会将Query直接传送到MySQL层,并等待执行结果。
串联起来
将前面的各个部分串联起来,Vitess中一个query的执行过程如下图所示:
TopoServer
Topo Server中存储了所有的元数据信息,这些元数据信息可以帮助VtGate将查询路由到正确的VtTablet上。TopoServer中包含了keyspace到Shards的映射信息,keyspace id到shards的映射信息和VtTablet上监听的端口信息(EndPoint)。VtGate上在内存中缓存了一份这些元数据信息并且一旦该元数据信息在toposerver上发生了变更就进行周期性的更新。
流式查询
一般来说,流式查询就意味着查询结果将作为流进行返回。在Vitess中,VtTablet和VtGate两者都会采用流的方式当自己产生的结果一旦可用就会立即返回。 VtTablet默认情况下会攒够从MySQL返回的固定行数 ,然后将他们发送回VtGate。上面的步骤会不断地重复,直到将所有的行都返回了。
Scatter Query
一次 scatter query,顾名思义,将会在多个shard上同时执行。在vitess中,一旦VtGate判定一个Query将会跨多个分片执行,就会立即生成一个ScatterQuery。然后VtGate会将Query发送给本次查询涉及到的所有VtTablets,最后会将各个VtTablets上返回的部分数据进行汇聚,最后返回给客户端。
网友评论