上周我们推送了 TiDB 团队职位解读文章,当天就有很多简历砸来,我们深深感受到了小伙伴们的热情~ 趁热打铁,今天我司首席架构师唐刘老师将带大家了解一下传说中「面试通过率最低、难度最高」的研发团队——TiKV 团队。
我们 Team 主要负责 TiKV 的研发工作,下图是我们产品的架构图,大家可以看到,无论是 TiDB 还是 TiSpark,都是从 TiKV 存取数据的,所以我们一定要保证 TiKV 的稳定和高效。
在我们官网招聘页面,TiKV 研发工程师的岗位职责就两个:
负责分布式数据库 TiKV 相关的设计,开发。
负责构建分布式压力测试框架,稳定性测试框架。
是不是特别简单?说实话,我们也想好好写清楚,但无奈 TiKV 这边要做的事情实在是太多,所以这里我会详细介绍一下。
TiKV 研发工程师职位信息:
https://pingcap.com/recruit-cn/engineering/tikv-engineer/
TiKV 是一个支持事务的、数据强一致的分布式 Key-Value 数据库。也许有人会说,造一个 Key-Value 数据库有啥难的,我不这么认为,因为造一个工业级、通用的、有超高性能的 Key-Value,真的是一件很难的事情。而且这个 Key-Value 数据库上面还加了很多限定词来修饰,要支持这些特性就更难了。下面我会一个一个的自底向上来说明 TiKV 是如何实现这些特性的。
TiKV 采用分层架构设计,这样的好处在于各个模块特性都是独立解耦合的,大家可以专注于某一层的研究和开发。但同时,这些独立的模块最终会形成 TiKV 这一个整体。所以我们内部还是会希望大家不只局限于某一个单一模块,而是要尽可能地精通多个模块,如果你是一个典型的自我驱动力很强的人,那么你在 TiKV 团队就能快速成长起来!
作为一个 Key-Value 存储系统,最底层当然是考虑如何去存储 Key-Value 了。在这里,我们并没有发扬程序员「自己造轮子」这种光荣的优良传统,而是直接使用 RocksDB。主要原因就在于 RocksDB 已经足够好,我们短时间造一个还真不可能比它强。与其冒风险花很长时间去弄一个自己的底层 Key-Value,还不如基于 RocksDB 来更加稳妥和保险。
但我们并不只是单纯的使用 RocksDB,在 RocksDB 这边,我们需要:
源码级别的精通 RocksDB。也就是我们在使用 RocksDB 的时候遇到了任何问题,我们都可以帮助 RocksDB Team 去 fix。之前我们已经帮 RocksDB Team fix 了几个严重的 bug 了。
调优 RocksDB。RocksDB 虽然上手简单,但里面那一堆的参数,你要把它们给折腾好,适配到不同的机型,也是一个困难的事情,这块就不光要求你对 RocksDB 非常熟悉,也需要对操作系统有很深入的了解。后面,我们的目标是能做到自动调优 RocksDB。
Titan。今年我们已经开始给 RocksDB 定制一个新的 engine,叫做 Titan,这个 engine 主要是用的 KV 分离的思想,将大的 value 从 LSM-Tree 里面移除,减少写放大。
基于 Intel 下一代硬件 AEP 的 RocksDB 优化。硬件一直在以超过我们想象的速度发展,当我们还在纠结如何优化 SSD 的时候,基于 NVM 的编程已经在兴起了,但现在很多的 NVM 环境都是基于模拟器的,而我们手上则有实际的 Intel AEP 盘。现在,我们正在跟 Intel 合作以及某高校合作,一起在 AEP 上面对 RocksDB 进行优化。
当然,在 storage 层面,我们还要做的更多,现在我们正在做抽象 storage API 的工作,当这个完成之后,TiKV 就能支持不同的存储引擎,譬如使用 LevelDB,WiredTiger 等等,或者你自己用 Rust 写一个 pure engine 也可以。但我觉得更令人激动的是,我们内部正在基于这种方式,让 TiKV 直接对接自研的 AP 引擎,这样我们就能实现真正意义上面的行列混存,这是一个非常有挑战性的工作,欢迎大家加入。
上面说完了存储引擎方面的工作,但这些只能解决单个机器数据存储的问题,作为一个分布式系统,我们必须要将数据复制到多个机器上面,保证数据的安全。这里,我们就要使用分布式一致性算法了。分布式一致性算法,现在无非就是两类,Paxos 和 Raft,我们选择了 Raft。
Raft 协议比较简单。但实话,如果真的要做一个工业级别高性能的 Raft 实现,难度还是非常大的,我们已经做了很多的优化,但还有很多工作要做,主要包括:
Joint consensus,安全的成员变更。当我们要进行集群扩容缩容的时候,采用的是每次变更一个节点的做法,但这个方式在一些情况下会有 corner case 问题。所以更好的方式就是 Raft 里面提到的 Joint consensus。
Follower snapshot。当一个新节点加入集群之后,通常都是 Leader 给这个新的节点发送 snapshot,但这样其实会造成 Leader 的压力比较大(因为 Leader 同时要处理客户端的读写请求),所以一种可行的做法就是让其 follower 给这个新的节点发送 snapshot,等新的节点接受完了 snapshot,Leader 才会发送 logs。
不对等网络环境的优化。现在我们遇到了很多用户,都是两地三中心的架构,也就是同城有两个 IDC,而异地有一个 IDC,所以这几个 IDC 之间网络环境是不对等的。但原生的 Raft 其实并没有考虑如何处理这样的情况, 我们考虑的做法是给节点设置 priority,只有高 priority 的 node 才能发起选举。或者考虑只能投票节点,这些节点不会存有实际的数据,只有 Raft 的原信息,用来投票。
Learner backup/restore/replication。对于一个分布式集群来说,如何高效的对整个集群进行备份,恢复以及支持实时复制是一件非常困难的事情,我们后续准备通过 Raft Learner 机制来做这个事情。通过 Raft 自带的 snapshot 以及 Log replication 机制,将数据备份到其他地方,譬如 S3,Ceph 等。
TiKV 采用 Google Percolator 模型来实现分布式事务,但现在我们的实现还有很多可以做的地方,主要如下:
Timestamp 的获取。一次事务,会从 PD 获取两次时间戳,虽然获取时间戳的速度很快,但毕竟还是有网络开销。我们可以通过一些方式,只从 PD 拿一次时间戳,也可能会考虑其他授时方案。
跟 Raft 整合,延迟 apply。现在一次写入,会在 Raft 上面生成两个 log,第一个 log 包含的是 Prewrite,而第二个则是 Commit,而我们都会把这两个 log apply 到状态机,但实际在处理 Prewrite 的时候,我们可以延迟 apply,等真正碰到对应的 Commit 再一起处理。
跟引擎的结合。如何高效的让事务跟底层引擎结合起来,让事务处理的更快,也是一个需要考虑的问题。譬如在 RocksDB 里面如何高效的获取特定版本的数据,或者扫描的时候如何快速的过滤掉不需要的数据,都是不小的挑战。
冲突事务的优化。现在的事务模型采用乐观锁机制,其实对冲突事务不友好,我们也需要对其进行优化。
Coprocessor 主要是为了支持 TiDB 和 TiSpark 的下推操作,随着越来越多的下推函数推到 Coprocessor 去执行,Coprocessor 就要做更多的事情了,主要包括:
支持更多的 Push 函数。这个其实就是将 TiDB 和 TiSpark 需要支持的函数实现。虽然看起来是一个辛苦活,但这对于个人克服 Rust 语言学习上的困难、快速参与 TiKV 开发,帮助都是非常大的。
资源隔离。对于查询语句,从 TP 发上来的和从 AP 发上来的我们的关注度是不一样的。同时我们也需要保证 AP 的大查询不能将整个系统资源给耗尽,影响到 TP 的操作。
查询的提速。譬如返回更多的 hint 给 TiDB 的优化器,用来调优后面的查询。
特定查询的优化。现在所有的查询都是走的统一的框架,生成一个 AST,依次执行,但实际对于一些特定查询,譬如 select count(*),我们完全可以将 AST 压扁,让其直接跟 engine 交互,得到数据,快速返回。
向量化支持。这是一个比较复杂的工程,涵盖了一系列优化,其核心是以列向量为单位进行计算。向量化通过一次性计算一批数据,改进了 Cache Locality 并更好地利用流水线,从而极大地提高计算速度。未来甚至还可以在此基础上实现指令级向量化—— SIMD。
当你的集群有几百台机器,有非常多的数据的时候,调度的作用就非常明显了。如果调度设计的不好,很容易导致整个集群性能的抖动,甚至把集群搞得完全没法工作。所以,调度也是 TiKV 里面非常重要的工作。在 TiKV 里面,我们需要考虑:
不同 workload 下面的调度。譬如如果出现了热点,调度器需要快速的检测出来,并且将热点的请求分散到不同的节点,分散压力。
模拟器。如何验证我们的调度程序正常工作?唯一的方法就是测试,但每次测试都搭建集群,插入非常多的数据,其实非常的麻烦,所以我们需要通过模拟器来简化这些事情。
可视化。除了通过模拟器,另一个查看调度是否正常的办法就是可视化,我们会将整个调度的过程展示出来,通过可视化就能知道集群是否在正常工作。
上面说了一些重要模块需要做的工作,对于 TiKV 来说,还有两个非常重要的地方,是我们非常关注的,就是性能和测试。这两块其实算是比较通用的,会涉及到所有的模块,主要是:
对各个模块进行性能测试,得到各模块的性能极限,为后面的性能优化提供指导。
对各个模块进行详细的测试,使用 failpoint 等对系统进行注入测试。
实践 Chaos,对系统进行大规模长时间的稳定性测试。
使用 TLA+ 验证系统设计的正确性。
设计并实现性能回归测试平台。任何提交,我们都能非常方便的知道与之前版本的性能对比,知道这次提交到底在哪些地方影响了性能。
使用 Jepsen 和 Porcupine 等验证系统的线性一致性。
操作系统的调优,包括 IO,network 等。
在 TiKV team,我们非常鼓励大家将自己做的东西通过文字表达出来。你可以参与《TiKV 源码解析系列》文章,让大家能通过你的文章深入的理解代码,也可以参与《 Deep Dive TiKV 系列》文章,让大家理解为什么我们要这么设计系统,它背后的原理到底是什么。
作为一个开源项目,我们需要通过自己的努力来回馈开源社区。我们会提供 Rust 培训课程,也会提供分布式系统学习课程,让大家能通过在网上自学就能用 Rust 来构建一个高可用的分布式项目。
我们非常鼓励大家出去布道。你可以参加我们各地 Office 定期举办的 Meetup,也可以去知名的公司进行技术交流,我们也会提供机会让你在国内知名的会议上演讲。对于优秀的同学,我们还提供参加国外 Meetup 的机会。
TiKV 作为 CNCF 的项目,无论在国内,还是海外,都有很多朋友关注,并且给我们贡献代码。你需要跟众多的开发者一起交流协作,共同完善整个项目。
“从理论到实践,从入门到熟练,TiKV 团队完善的培养计划让我快速成长。新的挑战每天都有,新的技能树每周都能开启,在这让我有一种回到学校的感觉,能和大家一起进步,真好!”
—— Overvenus
“在 PingCAP TiKV 团队,你不仅可以和各种大牛甚至语言创始者共同协作、开发、学习、进步,更重要的是,在掌握基础之后你可以非常自由地选择自己感兴趣的部分来改进 TiKV 这个产品。在这个过程中你可以由自己来设计一切并逐步将它打造出来。相信这种自己当 PM、自己来设计、自己来实现的开发方式能带给你全新的体验。”
—— Breeswish
“在这里你可以零距离接触一个分布式存储引擎的所有细节,并提出自己的改进、优化建议,快来一起享受写数据库的浪漫吧!”
—— Hicqu
“这里有很多聪明能干的小伙伴一起成长,有来自世界各地的 Rust 社区大佬,更有老司机们指路护航。工作即富有挑战又自由有趣,越来越多的深水区等待你的挖掘,快来打造你理想中的数据库吧!”
—— Nolouch
最后来说说要求吧,毕竟招人就像是相亲,总得有个门槛的。
公司目前还处在创业阶段,压力是不可避免的,而且现在我们用户特多(尤其是互联网头部用户),这就要求大家必须具备一定的抗压能力。
需要有分布式开发经验,至少 CAP,Raft 这些基础概念是需要了解的。当然,如果你有调度系统的开发经验,折腾过 Kubernetes,Mesos 等东西,那就更好了。
如果没有这两门语言的开发经验,有 C、Python 相关经验也没问题。当然,Rust 可能对一些同学是一个坎,就看你能不能克服了,毕竟这门语言实在太难上手了。
当然,我们也非常欢迎实习生。对于想来实习的同学,你只要觉得自己主动性强,肯学习,能写代码就可以了。我们有时候也直接会让实习生去解决用户问题,虽然会很有挑战,但能让你快速成长。
我们认为优秀的工程师或多或少有以下共同特质:
A Quick Learner
An Earnest Curiosity
Faith in Open Source
Self-driven
Get Things Done
如果你符合以上特质,欢迎进入招聘页面查看目前开放的工作机会:
https://www.pingcap.com/recruit-cn/join/#positions
简历投递通道: [email protected]
实习生:公司的各项福利和学习资源对实习生全面开放,更重要的是实习生还未毕业就有机会接触工业级项目,而且实习期间表现优异者将有机会获得校招绿色通道特权。如果小伙伴们时间不够充裕,也可以先从社区 Contributor 做起,或许下一期 Talent Plan 的主角就是你!
伯乐推荐:如果你身边有符合以上要求的小伙伴,也可以找我们聊一聊,推荐成功就有机会获得伯乐推荐奖励( iPad、iPhone、MacBook Pro 等等)。伯乐推荐邮件格式:[伯乐推荐] 候选人姓名-职位名称-推荐人姓名-推荐人手机号。