东方美学与软件设计

‘不立文字,直指人心’ — 六祖慧能 昨天正好在飞机上把原研哉的又一本关于设计的书看完了,书名就不提了,大概仍然是原研哉老师用他那种特有的平静的口吻描述关于设计的思考和社会的观察,引起了我对于软件设计审美的一些思考。熟悉我的朋友大概知道我一向对艺术和哲学有着偏爱,尤其是东亚的古典美学,看似离所从事的计算机行业很远,但是我一直认为在代码深处存在着相同的审美趣味。正好试着总结一下作为第二篇关于系统设计品味的文章,上次如果说是一篇关于‘术’的文章,这篇可能会更有‘道’的味道 :)。不过关于审美的事情通常是带着强烈的个人偏好,而且就像任何其他艺术形态一样,审美也是有流派的,如果对本文描述的东西不认同也实属正常,一笑了之就好。 东方美学的内核 在聊软件之前,我们先聊一下美学。仔细想想也蛮有意思的,长期以来我们都认为计算机科学是更加偏向工程学的范畴,也就是所谓的软件工程,但看看接近的学科,例如建筑,我们很自然的能够将泥瓦匠和建筑设计师看作是两种不同的职业,但是对于程序员和软件设计师很多时候是一体,于是对于系统设计品味的讨论通常会和工程学乃至管理学混在一起,即使有对于美学的讨论,也只是在一些 Geek 和 Hacker 的亚文化中,隐藏在一个个看似戏谑但是充满禅意的 Puns 和 Wordplay 里面,例如在 ESR 的《How To Become A Hacker》一文中关于 Hacker 生活方式中对禅宗和禅修的推崇可见一斑,我其实还蛮庆幸在我刚接触编程的年代(90年代中后期)赶上了黄金年代的尾巴,得以一窥,现在的年轻 Geek 们只能在计算机考古学中体验了 :)。 为了避免牵扯太多其他的内容,大概的范围会限定在禅宗和道家的审美,而且只会从‘表’上分析,内在的哲学和宗教的内容不会过多涉及。说到这个话题,大家不妨在脑子里想象一下典型的东方审美的例子:寥寥几笔加上大片留白的水墨画,雾气缭绕的山脉,日式枯山水庭院,Wabi-sabi,离日常生活近一点的,例如优衣库,无印良品,苹果(乔布斯时代)…如果总结几个关键字就是:崇尚简洁,没有攻击性,平静含蓄的表达,以小见大(通过小的细节隐喻出更大的意境)…值得注意的是,这并不是回避世界的复杂性,而是强调隐藏在复杂性的表面背后的根源是极简要素加上自洽的规则。 其实有这种审美倾向丝毫不意外,禅宗的内核中有很浓的存在主义和本体论色彩,例如铃木大拙(当代最有名的禅学大师之一,在西方尤其受到推崇)关于意识以及一切可能性的根源,也就是他口中的 Cosmic Unconscious 概念,又如道家的老子在道德经中关于‘道’的描述:‘有物混成,先天地生…道生一,一生二,二生三,三生万物…',都是关于这个审美内核精彩诠释,当然严格来说,道家和禅宗在审美上还是有一定区别的,道家更加崇尚与自然的融合,顺其自然,用当下流行的话就是‘躺平了’,是一种出世的美学,但是禅宗更加严肃,只为了达到心物合一的顿悟。但在表面上,这类东方的古典审美其实倒是暗合了当代西方的包豪斯设计的一些理念:简单并不意味着简陋,而是舍弃掉一切无用的装饰,直指本源。只是对于包豪斯来说,本源大致是从实用主义角度出发,东方这边的含义更深且丰富而已。 复杂系统的简洁之美 回到计算机的世界,复杂总是不可回避的,人类总是会在不停尝试创造超出自己理解边界的事物,正所谓创新。而且无穷的复杂性用有穷的代码来表示,本身就是一件非常充满禅学审美的事情。就像我经常举的一个例子:大家有没有想过,TiDB 核心大概百来万行代码,运行在 3 台机器上和运行在 3000 台机器上一样,都是这百来万行代码,但是 3 台机器的复杂性和 3000 台机器复杂性确是千差万别,人肉管理 3 台机器很轻松,但是管理好 3000 台机器,让它们高效稳定的协作这件事情,肯定超出了人作为个体的能力范围,等一下后面我会再聊到 TiDB 的例子。 同样的例子还有很多,例如大家比较熟悉的 Unix 哲学,已经有无数人阐述过,我也不追溯,后边我会用几个比较新鲜的例子,用来阐述复杂系统的简单之美,来让大家体会一下其中妙处。 元胞自动机 第一个例子,我想聊聊元胞自动机(Cellular Automata),元胞自动机大概是 50 年代由冯诺依曼提出的一个自动机模型,听名字很高级,但事实上非常非常简单,简单到小学生都能马上理解:想象一个 n 维度的无限网格(最好理解的是 2 维,大概就是类似棋盘的样子),每个格子会处于有限的状态,t 作为离散的时间概念,每一个 t 时刻的网格中每一个格子的状态是由 t - 1 时刻这个的格子的邻居格子( 2 维里面就是上下左右的几个)的状态决定,注意所有的格子都是平等的,受到同一种规则的支配。实现这么一个自动机,也就是百来行代码,最有名的实现是 Conway 的 Game of Life,生命游戏是一个二维的 CA 实现,想象每个格子是一个细胞,规则很简单(来自 Wikipedia):...

December 26, 2021 · 3 min · Ed Huang

做出让人爱不释手的基础软件:可观测性和可交互性

最近有一件事情让我印象特别深刻,作为引子和大家唠一唠:我们在内部做一些极端的流量回归仿真实验时,在 TiKV(TiDB 的分布式存储组件)上观测到了异常的 CPU 使用率,但是从我们的 Grafana Metrics、日志输出里面并没有看到异常,因此也一度困惑了好几天,最后靠一位老司机盲猜并结合 profiling 才找到真凶,真凶出现在谁都没有想到的地方:Debug 用的日志模块(澄清一下:目前这个 Bug 已经修复了,而且这个 Bug 的触发是在非常极端压力的场景下+日志级别全开才会出现,请各位用户放心)。 这篇文章并不是做 Bug 分析,我觉得更重要的是,找问题过程中我们使用的工具、老司机的思考过程。作为一个观察者,我看到年轻的同事看着老司机熟练地操作 perf 和在各种各样工具和界面中切换那种仰慕的眼神,我隐约觉得事情有点不对:这意味着这门手艺不能复制。 事后,我做了一些关于基础软件用户体验的调研,发现该领域的理论和资料确实挺少(大多数是 ToC 产品的研究,系统软件相关的大概只有 UNIX 哲学流派),而且缺乏系统化,依赖于作者个人「品味」,但是软件体验的好和坏显然存在,例如一个有经验的工程师看到一个命令行工具,敲几下就知道是否好用,是不是一个有「品味」的工具。 很多时候「品味」之所以被称为「品味」,就是因为说不清道不明,这固然是软件开发艺术性的一种体现,但是这也意味着它不可复制,不易被习得。我觉得这也不好,今天这篇以及可能接下来的几篇文章(虽然后几篇我还不知道写啥,但是先立个 Flag)会试着总结一下好的基础软件体验到底从哪里来。 作为第一篇,本文将围绕可观测性和可交互性两个比较重要的话题来谈。至于为什么把这两点放在一起聊,我先卖个关子,最后说。 可观测性 可观测性是什么?这可从我两年前发表的 《我眼中的分布式系统可观测性》 [1]一文中可见一斑,相同的内容我在这里就不赘述。随着在 TiDB 中对可观测性实践的深入,对这个话题有了更深的理解,为了更好的理解,我们首先先明确一个问题:当我们在聊可观测的时候,到底是谁在观测? 是谁在观测? 很多朋友可能会一愣,心想:这还用说,肯定是人,总不能是机器。没错,的确是人在观测,但就是这么一个浅显的道理往往会被软件设计者忽略,所以这两者的区别到底是什么?为什么强调人这个主体很重要? 要回答这个问题,需要清楚一个现实:人的短期工作记忆是很有限的。大量的心理学研究表明,人类工作记忆的容量大致只有 4,即在短期同时关注 4 项信息 [2],再多的信息就要靠分模块的方式记忆,如我们快速记忆电话号码的方式,以 13800001111 为例,我们通常不是一个个数字背,而是形如:138-0000-1111 进行分组。 在了解人的心智模型的一些基础假设和带宽后,我想很多系统软件开发者大概不再会炫耀:我的软件有 1000 多个监控项!这不仅不是好事,反而让更多的信息破坏了短期记忆的形成,引入了更多的噪音,让使用者在信息的海洋里花很多时间找关键信息,以及不自觉的分类(我相信大脑的一个不自觉的后台任务就是对信息建索引和分类,注意这同样是消耗带宽的),所以第一个结论:软件应用一屏的界面里面最好只有 4 个关键信息。那么,接下来的一个问题是:哪些是关键信息?什么是噪音? 区分关键信息和噪音 这个问题没有标准答案。对于系统软件来说,我的经验是:跟着关键资源走。软件其实很简单,本质就是对硬件资源的使用和分配,讲究平衡的艺术。关键的硬件资源无非也就下面几个,对于下面每一个关键资源在某个采样时间段(单点没有太多意义),都可以通过一些简单的问题的询问,得到对系统运行状态的大致图景: CPU:哪些线程在工作?这些线程都在干嘛?这些线程各自消耗了多少 CPU Time? 内存:当前内存中存储了哪些东西?这些东西的命中率情况?(通常我们更关注业务缓存)? 网络 I/O:QPS/TPS 有异常吗?当前主要的网络 I/O 是由什么请求发起的?带宽还够吗?请求延迟?长链接还是短链接(衡量 syscall 的开销)? 磁盘 I/O:磁盘在读写文件吗?读写哪些文件?大多数的读写是什么 Pattern?吞吐多大?一次 I/O 延迟多大? 关键日志:不是所有日志都有用,只有包含特定关键字的日志,人们才会关心。所以,有没有特定关键字的日志出现? 通过以上标准问题的灵魂拷问,必定可以对系统运行状态有一定的了解。...

December 3, 2021 · 4 min · Ed Huang

分布式系统 in 2010s :测试和运维

我觉得面对测试的态度是区分一个普通程序员和优秀程序员的重要标准。现如今我们的程序和服务越来越庞大,光是单元测试 TDD 之类的就已经很难保证质量,不过这些都是 baseline,所以今天聊点新的话题。 说测试之前,我们先问下自己,为什么要测试?当然是为了找 Bug。看起来这是句废话,但是仔细想想,如果我们能写出 Bug-free 的程序不就好了吗?何必那么麻烦。不过 100% 的 Bug-free 肯定是不行的,那么我们有没有办法能够尽可能地提升我们程序的质量?举个例子,我想到一个 Raft 的优化算法,与其等实现之后再测试,能不能在写代码前就知道这个算法理论上有没有问题?办法其实是有的,那就是形式化证明技术,比较常用的是 TLA+。 TLA+ TLA+ 背后的思想很简单,TLA+ 会通过一套自己的 DSL(符号很接近数学语言)描述程序的初始状态以及后续状态之间的转换关系,同时根据你的业务逻辑来定义在这些状态切换中的不变量,然后 TLA+ 的 TLC model checker 对状态机的所有可达状态进行穷举,在穷举过程中不断检验不变量约束是否被破坏。 举个简单的例子,分布式事务最简单的两阶段提交算法,对于 TLA+ Spec 来说,需要你定义好初始状态(例如事务要操作的 keys、有几个并发客户端等),然后定义状态间跳转的操作( Begin / Write / Read / Commit 等),最后定义不变量(例如任何处于 Committed 状态的 write ops 一定是按照 commit timestamp 排序的,或者 Read 的操作一定不会读到脏数据之类的),写完以后放到 TLC Checker 里面运行,等待结果就好。 但是,我们活在一个不完美的世界,即使你写出了完美的证明,也很难保证你就是对的。第一, Simulator 并没有办法模拟出无限多的 paticipants 和并发度, 一般也就是三五个;第二,聪明的你可能也看出来了,一般 TLA+ 的推广文章也不会告诉你 Spec 的关键是定义不变量,如果不变量定义不完备,或者定义出错,那么证明就是无效的。因此,我认为形式化验证的意义在于让工程师在写代码之前提高信心,在写证明的过程中也能更加深对算法的理解,此外,如果在 TLC Checker 里就跑出异常,那就更好了。 目前 PingCAP 应该是国内唯一一个使用 TLA+ 证明关键算法,并且将证明的 Spec 开源出来的公司,大家可以参考 pingcap/tla-plus 这个 Repo,以及我们的首席架构师唐刘的这篇 博客 了解更多。...

December 3, 2021 · 2 min · Ed Huang

分布式系统 in 2010s :硬件的进化

上篇 我们聊了软件构建方式和演化,今天我们来聊聊硬件吧! SSD 普及的深远影响 如果说云的出现是一种商业模式的变化的话,驱动这个商业革命的推手就是最近十年硬件的快速更新。比起 CPU,存储和网络设备的进化速度更加迅速。最近五年,SSD 的价格 (包括 PCIe 接口) 的成本持续下降,批量采购的话已经几乎达到和 HDD 接近的价格。 图 1 近 5 年 SSD 成本曲线 SSD 的普及,对于存储软件厂商的影响是深远的。 其一,是极大地缓解了 IO 瓶颈。对于数据库厂商来说,可以将更多的精力花在其他事情,而不是优化存储引擎上。最近两年发生了一些更大的变化,NVMe 正在成为主流,我们很早就在 Intel Optane 进行实验和投资,类似这样的非易失内存的技术,正在模糊内存和存储的界限,但是同时对开发者带来挑战也是存在的。举一个简单的例子,对于 Optane 这类的非易失内存,如果你希望能够完全利用它的性能优势,最好使用类似 PMDK 这类基于 Page cache Bypass 的 SDK 针对你的程序进行开发,这类 SDK 的核心思想是将 NVM 设备真正地当做内存使用。如果仅仅将 Optane 挂载成本地磁盘使用,其实很大程度上的瓶颈不一定出现在硬件本身的 IO 上。 下面这张图很有意思,来自 Intel 对于 Optane 的测试,我们可以看见在中间那一列,Storage with Optane SSD,随机读取的硬件延迟已经接近操作系统和文件系统带来的延迟,甚至 Linux VFS 本身会变成 CPU 瓶颈。其实背后的原因也很简单,过去由于 VFS 本身在 CPU 上的开销(比如锁)相比过去的 IO 来说太小了,但是现在这些新硬件本身的 IO 延迟已经低到让文件系统本身开销的比例不容忽视了。 图 2 Intel 对于 Optane 的测试...

December 3, 2021 · 1 min · Ed Huang

分布式系统 in 2010s :软件构建方式和演化

我上大学的时候专业是软件工程,当时的软件工程是 CMM、瀑布模型之类。十几年过去了,看看现在我们的软件开发模式,尤其是在互联网行业,敏捷已经成为主流,很多时候老板说业务下周上线,那基本就是怎么快怎么来,所以现代架构师对于可复用性和弹性会有更多的关注。我所知道业界对 SOA 的关注是从 Amazon 的大规模 SOA 化开始, 2002 年 Bezos 要求 Amazon 的工程团队将所有的业务 API 和服务化, 几条原则 放在今天仍然非常适用: All teams will henceforth expose their data and functionality through service interfaces. Teams must communicate with each other through these interfaces. There will be no other form of inter-process communication allowed: no direct linking, no direct reads of another team’s data store, no shared-memory model, no back-doors whatsoever. The only communication allowed is via service interface calls over the network....

December 3, 2021 · 2 min · Ed Huang

分布式系统 in 2010s :存储之数据库篇

回看这几年,分布式系统领域出现了很多新东西,特别是云和 AI 的崛起,让这个过去其实不太 sexy 的领域一下到了风口浪尖,在这期间诞生了很多新技术、新思想,让这个古老的领域重新焕发生机。站在 2010s 的尾巴上,我想跟大家一起聊聊分布式系统令人振奋的进化路程,以及谈一些对 2020s 的大胆猜想。 无论哪个时代,存储都是一个重要的话题,今天先聊聊数据库。在过去的几年,数据库技术上出现了几个很明显的趋势。 存储和计算进一步分离 我印象中最早的存储-计算分离的尝试是 Snowflake,Snowflake 团队在 2016 年发表的论文 《The Snowflake Elastic Data Warehouse》 是近几年我读过的最好的大数据相关论文之一,尤其推荐阅读。Snowflake 的架构关键点是在无状态的计算节点 + 中间的缓存层 + S3 上存储数据,计算并不强耦合缓存层,非常符合云的思想。从最近 AWS 推出的 RedShift 冷热分离架构来看,AWS 也承认 Snowflake 这个搞法是先进生产力的发展方向。另外这几年关注数据库的朋友不可能不注意到 Aurora。不同于 Snowflake,Aurora 应该是第一个将存储-计算分离的思想用在 OLTP 数据库中的产品,并大放异彩。Aurora 的成功在于将数据复制的粒度从 Binlog降低到 Redo Log ,极大地减少复制链路上的 IO 放大。而且前端复用了 MySQL,基本做到了 100% 的应用层 MySQL 语法兼容,并且托管了运维,同时让传统的 MySQL 适用范围进一步拓展,这在中小型数据量的场景下是一个很省心的方案。 虽然 Aurora 获得了商业上的成功,但是从技术上,我并不觉得有很大的创新。熟悉 Oracle 的朋友第一次见 Aurora 的架构可能会觉得和 RAC 似曾相识。Oracle 大概在十几年前就用了类似的方案,甚至很完美的解决了 Cache Coherence 的问题。另外,Aurora 的 Multi-Master 还有很长的路要走,从最近在 ReInvent 上的说法来看,目前 Aurora 的 Multi-Master 的主要场景还是作为 Single Writer 的高可用方案,本质的原因应该是目前 Multi-Writer 采用乐观冲突检测,冲突检测的粒度是 Page,在冲突率高的场合会带来很大的性能下降。...

December 3, 2021 · 2 min · Ed Huang

[演讲] The Future of Database 2021

这次我分享的主题和 2019 年还是一样的——《The Future of Database》,如果你是 PingCAP 的老朋友,参加过之前几次 DevCon 就会知道,这是我的一个保留节目。如果要说我哪里有一些与众不同的气质,我觉得除了发型之外,还有一个是对技术的信仰和执著。这个保留节目我们还是聊聊技术。 过去两年,**TiDB 在技术上发生的最大变化是什么?**可能有很多同学觉得性能变得越来越好,功能变得越来越多,生态功能越来越大,其实不是。 从一个程序员角度看,在过去两年中 TiDB 其实完成了一个很重要的转变,那就是开发模式的转变。上图中左边是一个工程师对着屏幕在写代码,这是我们早年在第一个办公室里面开始写 TiDB 第一行代码的状态。旁边放了一瓶可乐和披萨,想到什么写什么。现在 TiDB 整个研发流程越来越像右边这张图,一个小工厂流水线化做月饼。虽然现在离中秋节还稍微有点距离,还是很可爱。 TiDB 这两年最重要的一件事情,是研发流程以一个全新的发版模型去做软件工程,我们称它为“火车发版”模型。这个模型的特点,是我们会把很多大的 feature 以小的迭代进行逐步增量发布,意味着更易于管理发布周期。 很多人可能会说“关我什么事?”,这件事情非常重要的意义在于,TiDB 从一个纯粹社区的开源软件开始慢慢变成面向企业级的数据库产品。说得再接地气一点,用户真实场景里面需要的 feature 最快两个月就能合并到 TiDB 的主干,并交付给用户。 两年前,我的演讲题目也是《The Future of Database》,上图是两年前演讲的截图。向量化,当时这是一个挑战,现在已经完成了;TiFlash ,当时只是在草图上设计的一个架构,在 5.0 引入 MPP 后让它变成了一个真正的 Real-time HTAP 的数据库;IPC /异步提交,5.0 的性能和稳定性都得到了稳步提升;TiDB DBaaS,现在 TiDB Cloud 已经是服务千家万户,服务全球各个地方的真实产品;本地事务异地多活,两年时间也做完了。 两年前的五大构想,今天都变成了现实。 从 2019 年到现在的两年时间中,在**这些 feature 背后我们经历了什么?**是两年时间超过三万个 PR 的合并。人总是有成长的,两年前的我和现在的我区别是什么?发型没有变,T 恤也是一样的,变化的是 TiDB 合并了三万多个 PR。回头看我两年前的 PPT,我在思考一个问题,TiDB 的竞争力或核心优势是什么?很多数据库都说自己的核心优势是性能好、功能多。那么,TiDB 的优势是什么? 两年前我的 PPT 里面有一页叫 Everything is Pluggable,我觉得特别有味道,**TiDB****的真正优势在于技术开放性。**架构开放就意味着能够产生更多的连接,更多连接意味着更快的迭代速度、更多的可能性。 为什么 TiDB 的系统核心优势是开放性?大家可以花几秒钟时间去思考一下,这一个思考的角度,让我这两年慢慢开始变成一个哲学家。这个角度是:单机数据库和分布式数据库最本质的区别是什么?做分布式数据库的工程师的这些痛苦和幸福的根源在哪里?我们真正的敌人是什么?我们要解决什么样的问题?我们怎么解决这些问题?...

December 3, 2021 · 2 min · Ed Huang

我眼中的分布式系统可观测性

今天的文章我想从这张模糊的照片说起,相信很多小伙伴对这张照片并不陌生,这是去年人类第一次拍摄的 M87 中心黑洞的照片,从1915年,爱因斯坦提出相对论预言黑洞的存在到 2019 年我们终于第一次「看到」了黑洞的样子,中间整整相隔了 100 多年,这对于人类认识黑洞乃至认识宇宙都是一个里程碑式的事件。人类是一个感性的动物,所谓「一图胜千言」很多时候一张图传达的信息超过千言万语。 关于黑洞我不想展开太多,今天我们聊聊「望远镜」。 前几天,在 TiDB 4.0 的开发分支中,我们引入了一个新功能叫做:Key Visualizer(下面简称 KeyViz),说起来这个小工具也并不复杂,就是用不同颜色的方框来显示整个数据库的不同位置数据访问频度和流量。一开始我们只是仅仅将它定位为一个给 DBA 用来解决数据库热点问题的调优辅助小工具,但是从昨晚开始我就一直在把玩这个小东西,突然觉得它对于分布式数据库来说背后的意义远不及此,在 CNCF 对 Cloud Native 的定义中,有一条叫做「Observability」,通用的翻译叫系统的「可观测性」,过去我一直苦于寻找一个例子说明什么叫做一个「可观测」的系统,在 KeyViz 这个项目上,我找到了对这点绝佳的体现。 举几个直观的小例子,你知道 TPC-C 测试「长」什么样子吗?请看下图: 图中横轴是时间,纵轴是数据的分布,左半部分有零星的亮点,是数据导入的过程,,可以看到写入分散到多个区块;右边密集的色块是测试在运行时系统的实时读写状态,越暗表示流量越小,越亮表示流量越高。从密集的色块我们能够看得出来,workload 基本分布均匀,但是大概有两处是明显偏亮的区域,其中靠近最上方,有一个特别明显的局部访问热点(最亮的那条线)。 第二个例子,你见过 Sysbench 测试 「长」什么样子吗?看看下面: 左边比较密集的明亮黄块是导入数据阶段,右半段明暗相间的部分是进行 oltp_point_select 测试,因为选取的模式是 uniform 模式,并且导入的时候是 32 线程 32 张测试表,可以看到的数据和分布和访问都比较均匀。 如果你看懂了上面两个小例子,下面是一个小作业,这是我们模拟的一个实际用户的生产环境的照片,这个用户的系统遇到了一些瓶颈,你能看出问题吗? 上面几个小例子是让大家对 KeyViz 有个感性的认识,在介绍这个东西背后的意义前,我想先介绍一下 TiDB 这类典型的分布式数据库的系统架构,方便大家更好的理解。 顾名思义,分布式数据库,数据一定是分散在不同机器上的,对于一张表的数据,我们会在逻辑上切分成若干个连续的区间,将这些区间内的数据分给不同的机器存储,不管是写入还是读取,只需要知道目标数据属于哪个区间,就可以直接到那个机器上进行访问。然后加上对每一个区间的数据在物理上做多副本冗余实现高可用。如下图所示,Region 在 TiDB 的内部就是一个个连续的数据区间。 和很多分布式数据库不太一样的是,我们的 Region 的大小比较小(默认 96MB) ,另外数据的分布并不是静态的,而是动态的,Region 会像细胞一样分裂/合并,也会在不同机器之间移动进行动态的负载均衡。 现在回头看这个设计,还是觉得无比的简洁和优雅。对用户而言再也不用去思考怎么分库,怎么分表,数据在最底层的细胞就像有生命一样繁衍和迁徙。 然后问题就来了,对于这样的数据库而言,有没有一种办法能够直观地描述系统的运行时状态?我怎么知道它是不是「生病」了?我能不能预测这个系统的未来?我能不能发现未知的风险? 过去,不管是业务开发者还是 DBA,衡量一个数据库的状态,来来回回就是几个指标,QPS 、TPS、查询时间、机器负载(CPU、网络、磁盘),但是很多时候就像是盲人摸象一样对于系统的全局我们是不清楚的,再加上在一个分布式的架构下,很多时候,我们可能会被海量的数字蒙蔽了双眼。有经验一些的 DBA 可能能从多个指标里通过自己的经验,模糊构建出业务全局状态,但是到底这个经验往往是不可描述的,这就是为什么一些老运维,老 DBA 那么值钱的原因,但是我认为这种做事方式是很难 scale 的。现代医学有 CT 有 B 超有核磁共振,这些现代化的手段极大的促进了现代医学的发展,因为我们第一次能「看见」我们身体的内部状态,从而才能得出正确的判断,在计算机的世界道理也是相通的,最好通过某些工具让人更清晰的看到系统运行的健康状态、帮助诊断“病灶”,从而降低经验门槛和不确定性。 过去经常有朋友问我:「你说我这个业务适不适合使用 TiDB?」这时我们只能问,你的 QPS 多少 TPS 多少,数据量多少?读写比?典型查询?数据分布怎么样?表结构是什么呀?等等一连串的灵魂拷问,而且很多术语都非常专业,不是在这个行业摸爬滚打很久的老司机可能都搞不太清楚。有些信息可能是敏感的,也不方便共享。所以“预判 TiDB 到底适不适合某类业务”就成了一个玄学问题,这个问题困扰了我很久,很多时候也只能凭个人感觉和经验。其实这个问题也并不是 TiDB 特有,尤其是最近几年,几乎所有现代的分布式系统都或多或少有类似的问题。 在过去,一个物理机器的状态确实可以通过几个监控指标描述,但是随着我们的系统越来越复杂,我们的观测对象正渐渐的从「Infrastructure」转到「应用」,观察行为本身从「Monitoring(监控)」到「Observability(观测)」。虽然看上去这两者只是文字上的差别,但是请仔细思考背后的含义。关于这个话题,我很喜欢引用下面这张图:...

December 3, 2021 · 1 min · Ed Huang

大教堂终将倒下,但集市永存

作为一个在中国的数据库软件从业者,最近被不少朋友在微信上询问业内某厂商「团队整合」的新闻,我其实并不想对这个事情发表什么评论。我始终坚信:基础软件,未来只有开源一条路。如果不开源,或者说内核不开源的话,产品的生命力是有限的。所以,在这里想分享一些我个人有关开源与闭源的看法,希望大家看完这篇文章后能够有些自己的思考 :) 顺便提一下,看到这个标题,熟悉开源运动的朋友肯定会心一笑,没错,作为 ESR 的门徒,我从不掩饰对于《大教堂与集市》这篇著作的喜爱。另外作为从事开源的创业者,这几年的实践让我们对于 ESR 的这本书的理解更加的深入,我会试着在这篇文章总结一些我们经常被问到的问题,最后一部分我斗胆给 ESR 的理论在当今云时代的背景下做一些修订,另外我们讨论的软件范围仅限于基础软件(数据库,编译器,操作系统等)。 一、代码是核心竞争力吗? 我和一些闭源软件项目的作者聊过,大多数选择闭源的原因不外乎以下几种: 觉得自己的核心算法非常厉害,不希望竞争对手模仿 担心用户拿到代码,就不给钱了 没有找到或者建立自己的护城河 代码太丑,不好意思开源 怕被人找到 Bug 其中以前三种答案居多,我非常能理解,这些回答也都是非常正当的理由,只是这篇文章我们好好的就事论事的挨个分析一下,对于第四第五个理由,其实我不想过多展开,我们聊聊前两种,先看第一种,我在后边会聊聊第二种。 对于第一种原因,我们再深入思考一下,一般可能有下面两种情况: 我的核心代码很短,可能是一个很巧妙的算法,或者一套很巧妙的参数 我的工程上的设计和实现得很优秀,系统架构是领先的 ● 对于第一种情况,我一直以来的观点是:如果在同一个行业里面,除非你达到了彻彻底底的人才垄断,那么在一个充分竞争的环境,如果这个问题是一个高价值问题,那么你能想到的短短的 「核心算法」,别人也同样能想得到。天下没有银弹,计算机科学就是在无数种妥协和不完美中寻找平衡的艺术(当然,图灵奖级别的 idea 或者量子计算机这种现象级的东西另说,但是这种机会是很少见的),即使通过闭源创造出短期的垄断优势,但是这个平衡一定会被另一个竞争对手打破,最终也一定会出现一个优质的开源替代品全部吞掉(这个开源事实标准短期看甚至不一定是更好的)。 其实多数的产品优势是体现在工程实现上,也就是上面的第二种,一群优秀的工程师,在正确的设计下,构建出优质的软件。对于这种情况,无论开源还是不开源,竞争对手都没有办法很好的模仿,就像一个学霸,考了一个100分的答卷,把这个答卷给一个学渣看,学渣朋友肯定也没法马上变成学霸,因为代码只是结果,是什么样的思考和选择得到了这个结果,这个过程是没法开放的,所谓知其然不知其所以然,当然,就算你也很厉害,也有一批优秀工程师,短时间也做出了一个不错的产品,但是没关系,结局和前面提到那种情况也是一样的:只要你是闭源的,这个问题又足够普遍且高价值,那么长远来看一定会有一个开源的解决方案吞掉一切。这背后的原因其实和代码没有什么关系,因为代码在这里其实并不是核心竞争力。关于前面提到的第三种理由,我认为是和第一种类似,作者可能认识到代码并不一定是核心竞争力,但是没有构建好护城河的情况下,只能选择将代码作为护城河。 二、代码不是核心竞争力,那什么才是? 在聊真正的核心竞争力之前,我们来聊聊闭源软件的局限性。 我们看看一个闭源的软件的一生:立项的动机可能是某个公司或者个人对于一个市场机会的洞见找到了一个高价值的场景,通过开发一个软件能够很好的提高效率或创造价值,甚至可能就是一张来自甲方的合同,总之这个公司招募了一伙程序员,设计师,产品经理,开始项目的开发。一切顺利的情况,顺利的满足了甲方的需求,甲方也很开心的付钱了,然后这个公司发现,好像这个软件改一改(甚至不用改)也就能够在同行业另一个客户那边卖出去,这就太好了,感觉找到了一条致富路。可是好境不长,客户这边的场景和需求在变化,原来的软件可能不一定能够满足新的需求了,但是开发团队就这几杆枪,稍有不慎一个方向判断错误,可能时间和机会窗口就错过了。这就意味着,对于项目领头人的要求就很高,要求持续能够引领行业的方向。还有一种方式是挑选一个相对狭窄或迭代不快的领域,存活时间能够延长一些。对于甲方也很难受,总是感觉需求的满足慢半拍,甚至对于有些有着研发能力的甲方,因为受限于没有源码,就算知道如何改进,也只能干瞪眼。 其实这个问题的本质在于:闭源软件开发商虽然可能是技术的专家,但是并不一定是业务或者场景的专家,软件进化的速度受限于开发团队和产品经理自己的认知和见识的进化速度,除非开发商强大到能够持续引领整个行业的进化方向,否则无解。 其实这个问题,教员早就给出了答案:「…凡属正确的领导,必须是从群众中来,到群众中去。这就是说,将群众的意见(分散的无系统的意见)集中起来(经过研究,化为集中的系统的意见),又到群众中去作宣传解释,化为群众的意见,使群众坚持下去,见之于行动,并在群众行动中考验这些意见是否正确。然后再从群众中集中起来,再到群众中坚持下去,如此无限循环,一次比一次地更正确、更生动、更丰富…」 — 《关于领导方法的若干问题》, 1943 要我说教员放在当代,就算是当个程序员,也能是一个大师级别的。教员的这段话,包含两个关键的点,完美的解释了开源软件的生命力的来源,我下面的详细讲讲。 第一点,开源软件的生命力来自于场景的垄断,而背后更本质的垄断是人才垄断。 为什么强调从群众中来?回顾刚才我们闭源软件的那段,其实一个关键的点是,软件的初始动机虽然来自于少数人的洞见,但是持续保持洞见并不是一件容易的事情,这就是为什么很多技术团队或者产品团队容易「自嗨」,一旦脱离用户,极易出现这样的问题。闭源软件厂商触及用户的手段不外乎于传统的商业宣传和销售,用户从感兴趣到使用起来的门槛很高,实施的周期也很长,另外通常销售会站在产品团队和客户中间,通过一些信息不对称来获取超额的利润,其中最大的信息不对称就是封闭的源代码本身或者定制化。这导致的问题是,相比流行的开源软件,闭源软件没有办法高效的获取,吸收和理解更多的场景,这对于一个通用的基础软件产品来说通常是一个致命的问题,如果见过的场景不够多,更没有办法判断产品那些需求该做是普遍需求,哪些是伪需求坚决不做,我认为这就是做产品的「触感」。 对于一个流行的开源软件,本身不会有上面提到的问题:因为有足够多的用户,那么一定能看到足够多的场景,也能看到足够多的稀奇古怪的用法,这一个个用户的反馈,修过的一个个 bug,提出的一个个建议,会持续的产生类似「复利」的效果,你的软件越强壮,见过的场景越广,会进一步让你接触到更大的用户群,帮助软件变得更强大,如此循环。实际上开源软件本质上是通过放弃一部分通过信息不对称产生的潜在利润,换取了极其高效的传播和场景触及效率,但是有意思的是,实际上牺牲掉的这些潜在利润大概率也不一定真的牺牲掉,一来可能本身付费能力有限,二来可能实际上这些用户通过宣传站台二次传播或者代码贡献等方式回馈了项目本身。 在上面那个过程中还会产生一个更加厉害的效应:人才的垄断。正所谓「事在人为」,上面提到的场景垄断中种种的技术决策和实践都是人来操作的。一个流行的开源软件在变成事实标准的过程中,一定会培养出大量熟悉这个产品的工程师,用户,摇旗呐喊的粉丝,代码贡献者,甚至挑刺吐槽的人。传统意义上,大家理解的开源社区只是狭义上的开发者社区,只有贡献代码才算参与,但是我认为只要和这个产品发生关联的人,都算是社区的一部分,「人尽其材」才是构建开源社区的终极目标。这个优势是会随着时间的流逝不断累积,这个很好理解,举个例子:A 公司的工程师在 A 公司的工作中学习使用了 TiDB 也很好的解决了问题,然后这个工程师作为数据库专家跳槽到了 B 公司,遇到同样的问题时,你猜他会选什么? :) 第二点,迭代,迭代,迭代,只有高速迭代才能立于不败之地 上面教员的话里面有个关键的点,关于正向循环,也就是迭代。这个道理同样也适用于软件开发,软件从来都不是静止的,随着市场和竞争环境的变化,你今天的竞争优势,很可能明天就不是了。很多人都喜欢用静态的眼光看待问题,热衷于各种方案的横向对比,而忽略了进化速度,在这点上,我可能更看重的是同一个产品的纵向对比,举个例子:目前有 A, B, C三个方案,可能当下看这三个方案差距不大,也许在百分之五十之内。但是如果其中一个开源方案每次和自己半年前比都是在翻倍的提升(背后开源社区推动),但是闭源的方案的进步受限于团队规模和资源。这时候的选择除非是那种火烧眉毛的情况,否则一定应该选择一个迭代速度更快,增长率更好,更代表未来的方案,这个也很好理解。这是人的思维的一个惯性,人总是倾向用线性思维去看待问题,于是对非线性增长的事物往往会习惯性的低估。 说一个更加震撼的例子,我粗略统计了一下,从 2018 到现在,也就短短一年多时间,整个 TiDB 的 SQL 层这么一个项目发生了 30000 多次提交,有接近 60% 的源码被修改。也就是说,每一年的 TiDB 都和上一年是不一样的,是一个更适应当下的,更加进步的一个 TiDB,而且随着社区的不断壮大,迭代的速度会越来越快。我完全不能想象,如果 TiDB 是一个闭源软件,从第一行代码开始写,到现在短短的 5 年时间,如何能够到达现在这个成熟度,这一切都是得益于开源社区的带来的加速度和反复迭代。...

December 3, 2021 · 1 min · Ed Huang

In Community We Trust

前些天在与友人喝咖啡的时候,正好聊到关于 PingCAP 和 TiDB 的一些历史以及对于开源软件公司核心竞争力的理解,回顾这几年的创业生涯和 TiDB 社区的生长壮大,就像是一场巨大且正在进行中的社会学实验,原本零散的一些想法随着一条主线变得逐渐清晰,就想着写成文章总结一下关于社区对于开源软件以及开源公司到底意味着什么。 无处不在的网络效应 两种网络效应 很多人听说过网络效应(梅特卡夫效应:网络的价值与联网用户的平方数成正比),许多伟大的产品和公司通过网络效应构建起了强大的护城河。提到网络效应,经典例子在通信领域,例如手机,每多一个用户,对于所有用户的价值就越大,虽然大家也无意为他人创造价值,但是一旦开始使用,该行为就会帮助这个网络创造价值。很多我们熟知的 to C公司,尤其是社交网络和IM(即时通信软件) ,通过这个效应构建了极高的壁垒。NfX Venture 在他们的一篇博客(https://www.nfx.com/post/network-effects-manual/)中详细描述了很多种网络效应,在介绍社区之前,我想着重介绍下其中和开源软件相关的两种网络效应。 基于从众心理的网络效应 这类网络效应通常是从一些意见领袖开始,可能是行业大咖,可能是社交潮人,常常出现在一个新产品要去进攻一个老产品的市场时。尽管这个新产品相比市场的统治者来说不一定成熟,但它通常会带着一些鲜明的特色或者更加前沿的理念,吸引那些对「主流」不满或者希望突显自身前沿视野的意见领袖的支持,造成一种「很酷的人都在用,你不用你就要被淘汰了」的感觉。 这种感觉会在新用户纷纷加入时,形成从众心理的网络效应,但是**这类网络效应的持续时间不会太长。**细想一下就能知道:如果早期意见领袖只是因为突显「不同」而加入,那么在这个社区成为主流后,这些意见领袖就没有理由留下,追随这些人的粉丝可能会随之而去。另外,对于这个新产品来说,完善程度通常不如老产品,美誉和差评会在早期同时到来。此时,如果不快速通过网络效应打磨产品,获得更好的迭代速度,那么,这个网络效应是根基不牢的。一个好处在于,该效应在早期是事半功倍的。 回想 TiDB 早期的社区建设,也是因为几个创始人在 Codis 的工作以及在国内基础软件圈中积累的名声,和一些互联网技术圈中朋友的支持,形成最早的背书。 基于信仰的网络效应 **所谓「信仰」,就是基于对一个理念的认可而加入,从而形成网络效应。**这点在软件领域也不少见,自由软件运动和开源运动都是很好的例子。人嘛,总是要相信点什么。**这类网络效应的护城河是极深的,而且对于产品缺陷的容忍度极高。**因为信念是一个长期的念想,对于 TiDB 来说,这个念想形如:相信分布式是未来,相信云时代的业务需要像 TiDB 这样的数据库。但是这个目标又是足够有挑战的,值得长期为之努力。 基于信仰的网络效应可能在最早期和从众心理网络效应有点类似,其中的关键是社区核心人群对于产品背后的理念是否有坚定信仰。反之,如果只是简单地秀优越感,是不会长久的,随着兴趣衰减,网络效应也会崩塌。 网络效应对于基础软件的意义 对于基础软件来说,我一直坚持两个观点: 基础软件是被“用”出来的,不是“写”出来的。 迭代和进化速度是这类软件的核心竞争力。 这两点恰恰是网络效应能带来的,虽然价值链条不像IM那样明显,但是,网络效应存在的基础是新用户给老用户带来的额外价值。而基础软件的价值,体现为以下几点: 可控的风险(稳定性) 更多的场景适应性(发现新的适用场景和持续提升性能) 良好的易用性 对于风险控制来说,越多人用意味着风险被越多人均摊,其中的一个假设是:我不特别,我遇到的问题别人应该也遇到过,一定有人能比我早发现并修复它。这个假设在一个成熟且活跃的基础软件社区是成立的,因为基础软件的场景边界相对清晰,在适用范围内的路径大致相同,同一条路径走多了,坑自然就少了。只要有一个人踩到坑,反馈回社区,不管最后是谁修好的,这个行为对于其他用户都是受益的。 同样的逻辑,对于场景适应性来说也成立。个体的认知总是带有局限性,即使是项目的创始团队,也不见得对于某个具体的应用场景有深刻理解。社区用户的创造力是无穷的,一些设计外的使用路径可能会出奇地好用,从而发展出新的优势场景。同样地,只要有一个成功案例,那么对于其他具有相似场景的用户来说,软件的价值就增加了, TiDB 和 Flink 组合成的实时 HTAP 数据处理方案,就是一个很好的例子。 对于易用性改进的逻辑和稳定性类似,我就不赘述了。利用网络效应带来的飞轮效应改进软件,这个思路我在《大教堂终将倒下,但集市永存》一文中也提到过。 社区的成熟度曲线和必经阶段 社区的诞生 在 GitHub 上开放你的源代码,甚至使用公开的 Git 工作流,都不是社区诞生的时刻。一个社区真正诞生,是在你和你的代码之外,开始有第三者介入并产生连接的时刻,可能是收到第一个外部 PR,可能是收到第一个外部 issue,这些才是社区的开端。社区始于连接,也成就于连接。开放源代码并不等同于开源,很多团队和项目在开放源代码方面花费了很多时间,却忽略了代码及背后团队的社区化,这是很可惜的。 死亡鸿沟和希望之坡 就像《跨越鸿沟》这本书中提到的,开源软件也有自己的生命周期曲线,这是和社区息息相关的。 图中断层出现的原因是产品成熟度迟迟没有跟上,用户过来以后发现都是坑,随之而来的各种差评会让早期支持者和创始人疲于奔命甚至而失去兴趣。 **对于一个开源软件,断层的体现可能是经历早期快速增长后,来到长达 1~2 年的静默期,增长几乎停滞。**对于社区来说,几乎所有的精力都用在给早期用户填坑,期间会有用户自然增长但流失率也非常高。这个阶段对于资源的消耗非常大,社区的核心贡献者也会非常累,如果熬不过去就死了,所以说是“死亡鸿沟”。...

December 3, 2021 · 1 min · Ed Huang