系统设计中的快速估算技巧

2022-07-19 14:51:41 浏览数 (2)

拿到一堆数据,去做架构也好,设计也好,可行性分析也好,工程上需要的是严谨。但是也有很多场景,比如即时的问题争辩和讨论,我们往往需要的是快速、直接的估算,这样的数据显然不需要非常精确,甚至可以说它一定会非常粗略,我们的目标往往只停留在 “量级” 的级别,但是我们依然可以对方案有一个具体的、量化的认知,这比像 “海量”、“高吞吐”、“低延迟” 这类感性的、描述性的表述还是要清晰和有力得多。

举个经典的例子,已知 Twitter 2020 年大约有 2000 亿(200 billion)的推文(tweets)发推服务的吞吐量(TPS, transaction per second)是多少,网络带宽要占用,要存储它们需要多大的磁盘容量?

听起来是不是挺难的?其实并不是。我们可以用一点快速估算的技巧,它在有些场景下很有价值,且其实并不难,需要经过简单的练习。

  • 1 估算的例子
    • 1.1 吞吐量
    • 1.2 带宽
    • 1.3 存储
  • 2 重要的数值
    • 2.1 数据类型的空间占用
    • 2.2 时间数量级
    • 2.3 单机吞吐量上限

估算的例子

回到 Twitter 那个问题,我们来实际操作一遍。

吞吐量

首先,每个推文可以认为只写一遍,那么,200,000,000,000 / 365 days / 24 hours / 60 min / 60 sec 就可以得到大致的一个写的吞吐量了。

一般需要估算的时候,是来不及去拿计算器的,我们可以简算:

  • 365 days 算多一点,近似于 400 days,这样 200 billion / 400 = 500 million
  • 24 hours 算多一点,近似于 25 hours,这样 500 million / 25 = 20 million
  • 60 min 算少一点,近似于 50 min,这样 20 million / 50 = 400 thousand
  • 60 sec 算少一点,近似于 50 sec,这样 400 thousand / 50 = 8000

你看,这样这几个除数,有的多算一点, 有的少算一点,这就是让除法尽量简便的技巧。它得到的结果是,用于发推的写请求是每秒钟 8000 个。熟练了以后半分钟就可以得到结果了。

另外一个技巧是,尽量习惯用英文的 thousand、million、billion,数字的话每 3 位点一个逗号,比如 1,000,000,000。我以前习惯用中文的万、亿、兆,当然也可以,但是由于多数阅读材料和技术讨论的时候用的都是前一种方式,就很容易搞乱了。

此外,一天 24 小时有 60*60*24=86400 秒,这个数值得记住,因为总是被反复用到,上面的估算也可以直接应用这个数来简化过程。

如果你用计算器算上面的算式,可以得到大概是 6000 多个,也就是说,估算得到的结果和实际严格计算的结果是接近的。实际上,它们只要不差到一个量级,往往并不会影响我们在工程方面大的架构、评估和设计。

带宽

好,下面计算带宽,还是非常粗略的方式。我们假设平均每条推文 200 个字符,每个字符占用 2 个字节(byte),这样每条推文就占用了 200 * 2 = 400 byte,因此带宽就是 400 byte * 8000 = 3,200,000 bytes/second,也就大约 3MB / sec。

这里还是用了估算,尤其是软件的世界里面,从 B(byte,或者 B,注意它是大写的 B,表示字节,不是小写的 b,bit 是位,1 byte == 8 bits)到 KB 是 1024 倍,但是我们可以近似为 1000 倍,从 KB 到 MB 同理。

存储

存储的算法也是类似的,一年 200 billion 个推文 * 400 bytes = 80,000 GB = 80 TB。

你看,这些数据就 “形象” 得多了,在做进一步权衡和设计的时候,对于容量和性能上的需要,心里就有谱了。

当然,我们可以对上述数据做一些调整和延伸,例如,我们在设计系统容量,那么我们希望系统能够处理峰值,并且保留一定的 overhead 和 buffer,那么我们可以简单地给算得的值乘以 5 来得到一个范围上限;再比如,我们算了写操作的吞吐量,如果要考虑读操作的吞吐量,我们可以简单地给写操作的结果乘以一个倍率(比如 10)。

重要的数值

在上面的过程中,可以看到,对于软件系统来说,工程上面有一些数值是需要了解的,或者说,它们是 “常识”,或者 “基础”,从而方便地帮助我们做出合理的估算。

数据类型的空间占用

在很多系统中,Boolean 占用 1 个字节,字符占用 2 个字节,Integer/Float 是 4 个字节,Long/Double 则是 8 个字节。

时间数量级

Jeff Dean 十年前有一个著名的分享,介绍了他认为重要的系统的数值。我觉在讨论多数系统来说,有这样几个关于时间的数值(参考数量级)比较常见(注意时间单位的关系:1 秒 = 1000 毫秒 (millisecond) = 1,000,000 微秒 (microsecond) = 1,000,000,000(nanosecond)):

  • CPU 访问(包括 CPU 缓存):10 纳秒
  • 内存访问:100 纳秒
  • HDD 磁盘访问:10 毫秒,如果是 SSD 大约快 100 倍
  • HDD 磁盘吞吐量:100 MB/s,如果是 SSD 则高几倍
  • 同机房网络时延:1 毫秒
  • 异地网络时延:10 毫秒
  • 国际网络时延:100 毫秒

单机吞吐量上限

  • Web 服务器的 QPS:1000
  • RDB 单机 QPS:1000
  • NoSQL DB 磁盘单机 QPS:10K
  • 内存访问单机 QPS:1M

如果你觉得还有别的重要和常用的数值,也欢迎告诉我。

掌握这样的技巧以后,可以练习一下。比如经典的短网址应用设计,如果每年有 1 billion 的新网址被添加进来,短网址读写服务各自的吞吐量是多少?需要消耗多少存储空间?需要多少台应用服务器?

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《四火的唠叨》

0 人点赞