作者:沈泰宁 唐刘
许多人眼中的 PingCAP Talent Plan 可能就是 github.com/pingcap/talent-plan 这个项目,但从内容角度来说并不完整,这个 Repo 只是线上课程的内容,我们还有与其配套的线下课程。
本文将从课程设计的角度和大家聊一聊 PingCAP Talent Plan(TiKV 方向)课程,包括课程设计的逻辑、课程设计中遇到的困难,以及大家在学习过程中常见的问题和解答等。
PingCAP Talent Plan 是什么?
TiDB 是一个新型的开源分布式关系型数据库,目标是希望在大数据和云时代的新的业务需求下,帮助大家更好地解决数据大规模存储和实时计算的问题。我们听说很多同学跟我们反映他们很想参与到这些项目中去,但遇到了一些问题:
-
编程语言是参与项目的敲门砖。Golang 和 Rust 都比较新,需要一定的学习,是最直接的高门槛。
-
理论知识是深度参与的基础。从理论到实践有一道鸿沟,并不是这么容易跨越。
为了解决上述问题,我们启动了 PingCAP Talent Plan。目前课程主要分为两个方向,面向 SQL 优化器、分布式计算的 TiDB 方向,和面向大规模、一致性的分布式存储的 TiKV 方向。课程大体分成线上学习阶段和线下学习阶段,线上课程的主要目标是帮助大家从编程语言开始,学习并掌握 Golang 和 Rust,逐步学习关键的理论知识。
TiKV 方向课程内容
TiKV 是 TiDB 的分布式存储层,它本身也是一个高性能、可水平扩展、支持分布式事务的 Key-Value 数据库,目前已经成为了 CNCF 的孵化项目。在课程内容的制定上,我们主要参考了 TiKV 现有的技术栈:
-
Rust 编程语言。TiKV 主要使用 Rust 开发,根据 GitHub 统计,99.5% 的代码是 Rust。我们选择 Rust 主要看中了它的内存安全和高性能。
-
Raft 一致性算法。Raft 一致性算法主打可理解性,业界也有成熟的实现,TiKV 使用 Raft 算法同步节点之间的状态。
-
Percolator 分布式事务算法。分布式事务是 TiKV 很重要的功能,TiDB 的事务也是基于这个算法改进的。
语言真的是门槛吗?
坊间传闻 Rust 学习曲线非常陡峭,「rust steep learning curve」 关键词在 Google 上有超过 70 万条搜索结果。诚然,Rust 有些概念确实比较隐晦,比如 'static lifetime,Sync 和 Send,但它们也仅仅知识隐晦罢了,理解起来并不困难,结合我们的个人经验来看,在实际编写 Rust 代码过程中也很少遇到不明所以的编译问题,Rust 编译器对于大部分的错误都提供了详细的解释,我们只要按照编译器的指导修改代码即可。所以“Rust 学习曲线陡峭”或许是我们的刻板印象导致的。
纸上得来终觉浅,我们一致认为学习一门语言的最佳方法就是「动手去写」。为了让大家改变对 Rust 的印象,也为了让新手能有一个平缓的开始,Brian(TiKV 成员,Rust 语言主要开发者)编写了一套手把手的 Rust 教程——Practical Networked Applications in Rust,这个教程的目标是带领大家循序渐进地开发一个 KV 存储服务。
-
Tools:Rust 提供了完整周边开发工具,比如包管理工具 - Cargo,代码格式化工具 - rustfmt,代码 linter - clippy,它们将给我们的开发带来极大帮助。
-
I/O:在这个章节我们将学习 Rust 中的 I/O 操作,错误处理,比较并使用不同的 collection 类型。除此之外,还将使用 failure 和 serde 这两个库来构建强健的持久化 KV 存储。
-
Networking:Rust 标准库提供了完整的网络接口,我们将使用标准库实现 client-server 的持久化 KV 服务,期间将学习 Rust 强大的 trait 系统,logging 和 benchmarking。
-
Concurrency:相信写过并发编程的同学一定也写过数据竞争 ,在 Rust 中这将不复存在。这个章节我们将深入介绍 Sync 和 Send,体验 Rust 的「Fearless Concurrency」。
教程的内容足够深入,相信大家在完成后能无障碍地使用 Rust 进行日常开发。语言将不再是门槛问题。
PS:目前课程还在开发中,之后将添加异步章节,教大家使用 Future 进行异步编程。
带你突破两个重要的分布式算法
大家在阅读 TiKV 源码时,如果不了解 Raft 和 Percolator 算法,就很容易迷失方向,不知如何下手。就算了解这两个算法,实操过程中也有可能出现“知道大体做什么,却不明白为什么要这么做”的情况。因此在 Rust 语言课程完成之后,我们将继续带大家学习这两个重要的分布式算法。
关于 Raft,我们直接采用 MIT 6.824 课程,并将 Golang 的教材移植到了 Rust。6.824 提供丰富的测试,从 leader 选举一路测到线性一致性。在移植教程的时候,我们想尽可能地使用最简单的代码来实现,方便大家理解课程内容。但是移植过程并非一帆风顺,其中最大困难是 goroutine 的代码。在 Golang 可以随时开启 goroutine 执行异步的代码,但是 Rust 没有类似的功能,考虑再三,我们最后决定使用 Future 来写这类代码。
在移植完代码后,我们还验证了代码的正确性,验证 Raft 的测试框架教程的思路也很简单,用一个正确实现了 Raft 的库来跑一遍教程中的考核测试。我们选择了 github.com/pingcap/raft-rs 这个项目,测试一遍后修复了几个 BUG。不过事实证明只测试一遍是不够的,课程发布后社区小伙伴在学习过程中,又陆陆续续发现并解决了几个 BUG,在这里特别感谢 @wjhuang 和 @NingLin-P 两位同学的贡献。
至于 Percolator,由于没有现成的教学课程,我们决定从零开始设计。好在有一部分可以直接复用 6.824 代码,比如网络框架,它是比较通用的网络测试框架,可以模拟多种常见的网络错误,比如丢包、乱序等。Percolator 的测试也比较丰富,从 TSO 到 lost update 再到 read/write skew 最后到网络错误,都有覆盖。
学完这两个算法后,相信大家能达到“知其然,又知其所以然”的程度,再看 TiKV 代码的时候不会一头雾水。之后我们还将补充更多内容,比如 multi-raft、集群调度等,终极目标是让大家可以实现一个简易版 TiKV。
**另外值得一提的是,在线下课程中,我们将着重介绍 TiDB/TiKV 架构,带领大家了解实现原理与细节,还有专门的 Mentor 指导大家深度参与 TiDB/TiKV 开发。**更多的细节已在 这篇文章 中披露,在这就不赘述了。
FAQ
PingCAP Talent Plan 已经成功举办了两期,期间我们收集了学员的一些问题,在这里挑几个比较有意思的和大家分享一下。
Q1:github.com/pingcap/talent-plan 是如何组织内容的?
A1:talent-plan repo 里面有 3 个文件夹,/tidb 存放着 TiDB 相关实验,/rust 存放 Rust 课程,/dss 存放 Raft 和 Percolator。
Q2:dss 是什么意思?
A2:好问题,可能我们内部人员都不一定知道。dss 其实是 Distributed Storage System 的缩写。
Q3:Raft 测试为什么会卡住?
A3:大部分情况是在 RPC 的 handler 里面写了会阻塞的代码,受限于 Rust 的 Future 机制,我们不能 100% 地模拟 goroutine,后台执行 Future 的线程数量是有限的,如果 RPC 会阻塞,并发上来后就会卡住。
Q4:dss 为什么会 #[allow(dead_code,unused)]?
A4:这是因为我们留了一些公开 API 交由学员实现时使用,测试本身不会直接用到,这就导致了 dead code 的误报。这些 allow 我们是要求学员在提交的作业的时候去掉的。有不少学员没有注意这点而被扣分了。
Q5:dss 需不需要写注释?
A5:需要!不写会扣分。我们坚信注释是代码的一部分。
关于 PingCAP Talent Plan 的 TiKV 方向的课程暂时就介绍到这里,最后向 MIT 6.824 的工作人员致谢,感谢他们开源了优秀的 Raft 教材。