TiKV 是如何存取数据的(下) - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
PingCAP
V2EX    Rust

TiKV 是如何存取数据的(下)

  •  
  •   PingCAP 2018-10-12 11:59:10 +08:00 3674 次点击
    这是一个创建于 2612 天前的主题,其中的信息可能已经有所发展或是发生改变。

    上篇文章中,我们介绍了与 TiKV 处理读写请求相关的基础知识,下面将开始详细的介绍 TiKV 的读写流程。Enjoy~

    RawKV

    TiKV 提供两套 API,一套叫做 RawKV,另一套叫做 TxnKV。TxnKV 对应的就是上面提到的 Percolator,而 RawKV 则不会对事务做任何保证,而且比 TxnKV 简单很多,这里我们先讨论 RawKV。

    Write

    当进行写入,譬如 Write a = 1,会进行如下步骤:

    1. Client 找 PD 问 a 所在的 Region

    2. PD 告诉 Region 相关信息,主要是 Leader 所在的 TiKV

    3. Client 将命令发送给 Leader 所在的 TiKV

    4. Leader 接受请求之后执行 Raft 流程

    5. Leader 将 a = 1 Apply 到 KV RocksDB 然后给 Client 返回写入成功

    Read

    对于 Read 来说,也是一样的操作,唯一不同在于 Leader 可以直接提供 Read,不需要走 Raft。

    TxnKV

    Write

    对于 TxnKV 来说,情况就要复杂的多,不过大部分流程已经在 Percolator 章节进行说明了。这里需要注意的是,因为我们要快速的 seek 到最新的 commit,所以在 RocksDB 里面,我们会先将 TS 使用 bigendian 生成 8 字节的 bytes,然后将这个 bytes 逐位取反,在跟原始的 key 组合存储到 RocksDB 里面,这样就能保证最新的提交存放到前面,seek 的时候就能直接定位了,当然 seek 的时候,也同样会将对应的 TS 按照相同的方式编码处理。

    譬如,假设一个 key 现在有两次提交,commitTS 分别为 10 和 12,startTS 则是 9 和 11,那么在 RocksDB 里面,key 的存放顺序则是:

    Write CF: a_12 -> 11 a_10 -> 9 Data CF: a_11 -> data_11 a_9 -> data_9 

    另外,还需要注意的是,对于 value 比较小的情况,TiKV 会直接将 value 存放到 Write CF 里面,这样 Read 的时候只要走 Write CF 就行了。在写入的时候,流程如下:

    PreWrite: Lock CF: W a -> Lock + Data Commit: Lock CF: R a -> Lock + 10 + Data Lock CF: D a Write CF: W a_11 -> 10 + Data 

    对于 TiKV 来说,在 Commit 阶段无论怎样都会读取 Lock 来判断事务冲突,所以我们可以从 Lock 拿到数据,然后再写入到 Write CF 里面。

    Read

    Read 的流程之前的 Percolator 已经有说明了,这里就不详细解释了。

    SQL Key Mapping

    我们在 TiKV 上面构建了一个分布式数据库 TiDB,它是一个关系型数据库,所以大家需要关注的是一个关系型的 table 是如何映射到 key-value 上面的。假设我们有如下的表结构:

    CREATE TABLE t1 { id BIGINT PRIMARY KEY, name VARCHAR(1024), age BIGINT, content BLOB, UNIQUE(name), INDEX(age), } 

    上面我们创建了一张表 t1,里面有四个字段,id 是主键,name 是唯一索引,age 是一个索引。那么这个表里面的数据是如何对应到 TiKV 的呢?

    在 TiDB 里面,任何一张表都有一个唯一的 ID,譬如这里是 11,任何的索引也有唯一的 ID,上面 name 就是 12,age 就是 13。我们使用前缀 t 和 i 来区分表里面的 data 和 index。对于上面表 t1 来说,假设现在它有两行数据,分别是 (1, “ a ”, 10, “ hello ”) 和 (2, “ b ”, 12, “ world ”),在 TiKV 里面,每一行数据会有不同的 key-value 对应。如下:

    PK t_11_1 -> (1, “ a ”, 10, “ hello ”) t_11_2 -> (2, “ b ”, 12, “ world ”) Unique Name i_12_a -> 1 i_12_b -> 2 Index Age i_13_10_1 -> nil i_13_12_2 -> nil 

    因为 PK 具有唯一性,所以我们可以用 t + Table ID + PK 来唯一表示一行数据,value 就是这行数据。对于 Unique 来说,也是具有唯一性的,所以我们用 i + Index ID + name 来表示,而 value 则是对应的 PK。如果两个 name 相同,就会破坏唯一性约束。当我们使用 Unique 来查询的时候,会先找到对应的 PK,然后再通过 PK 找到对应的数据。

    对于普通的 Index 来说,不需要唯一性约束,所以我们使用 i + Index ID + age + PK,而 value 为空。因为 PK 一定是唯一的,所以两行数据即使 age 一样,也不会冲突。当我们使用 Index 来查询的时候,会先 seek 到第一个大于等于 i + Index ID + age 这个 key 的数据,然后看前缀是否匹配,如果匹配,则解码出对应的 PK,再从 PK 拿到实际的数据。

    TiDB 在操作 TiKV 的时候需要保证操作 keys 的一致性,所以需要使用 TxnKV 模式。

    结语

    上面简单的介绍了下 TiKV 读写数据的流程,还有很多东西并没有覆盖到,譬如错误处理,Percolator 的性能优化这些,如果你对这些感兴趣,可以参与到 TiKV 的开发,欢迎联系我 [email protected]

    6 条回复    2018-10-18 14:06:12 +08:00
    ihipop
        1
    ihipop  
       2018-10-13 09:44:09 +08:00 via Android
    公司也在用 tidb,但是每次 ddl 进度靠猜这个很痛苦,有全局状态监控吗?
    PingCAP
        2
    PingCAP  
    OP
       2018-10-16 10:16:46 +08:00
    @ihipop 要看具体情况,可以把相关细节发送到 [email protected] ,会有专业同事协助处理。
    ihipop
        3
    ihipop  
       2018-10-16 10:41:59 +08:00
    @PingCAP 不是付费用户 也可发邮件吗?
    PingCAP
        4
    PingCAP  
    OP
       2018-10-16 13:32:15 +08:00
    @ihipop 不管是不是付费用户,或者只是对 TiDB 技术细节感兴趣的,遇到的问题都可以发邮件到 [email protected] 沟通,或者在 google 邮件组发帖也可以,https://groups.google.com/forum/#!forum/tidb-user
    ihipop
        5
    ihipop  
       2018-10-18 11:38:36 +08:00
    @PingCAP 正好最近遇到一个诡异的索引问题 我发邮件咨询下
    PingCAP
        6
    PingCAP  
    OP
       2018-10-18 14:06:12 +08:00
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     926 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 19:40 PVG 03:40 LAX 11:40 JFK 14:40
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86