logo

削峰

顾名思义,将突发的流量高峰削平。大促的时候,系统顶不住,其实就是那么一会儿顶不住,只要初期的高热度下去了,系统的整体负载会迅速下降到没那么危险的水平。所以,对付突发流量,削峰是第一要务。

缓存——饮鸩止渴

请原谅笔者用饮鸩止渴这个词形容 95% 的 Web 系统的真正性能顶梁柱,实际上缓存的贡献远不止于此。

  1. 缓存以降低数据更新频率为代价,极大地提升了读取 API 的 QPS 极限
  2. 缓存可以设计成多级,形成一个逻辑上的“存储器山”
  3. 缓存可以像事务隔离级别一样划分成好几种“性能+数据一致性”级别

但是,使用缓存确实是在饮鸩止渴:缓存在带来性能的同时,大幅削弱了数据库提供的“单点性”,为系统失效埋下了一堆地雷。

缓存的毒性无法消除,一旦系统的某些部分失效,这杯毒酒就会发作,但是会不会把自己毒死还要看架构水平和基建能力:你的机房别随便断电,你的服务器别随便宕机,你在喝下缓存毒酒之后,就能活的够长。

终极缓存方案

我们前面章节中讨论过的 OceanBase 就采用了一种终极缓存方案:

  1. 内存不是快吗,那我就把所有热数据全部放到内存里
  2. 那对热数据的修改怎么办?redo log 落盘啊
  3. 你说数据库重启怎么办?上冗余,一个节点一时半会儿起不来也没问题
  4. 整个集群重启呢?都天灾了,集群重启后,停止服务一个小时还是可以接受的吧

12306 每天夜里都要维护一个小时,笔者没有证据地胡乱猜测一下,它在将 redo log 落盘。参考资料:《12306互联网售票系统的架构优化及演进》

队列——欢迎来到地球

缓存可以削“读”的峰,队列就是拿来削“写”的峰的。

队列的思想其实早就贯穿在人类社会的每一个角落了:超市结账需要排队,做核酸需要排队,火车站打车需要排队,网上抢购商品也需要排队。排队的本质是将一拥而上购买变成了“异步”购买:你想买东西?先排队,过段时间轮到你了,看看商品有没有卖完,没卖完你就能买到。

排队的思维特别好理解,而现实中防止超售功能也确实是基于排队功能做的。传统数据库的事务隔离属于强迫用户等待,而现在使用队列系统来处理排队,排队这件事情才真正异步了起来。

奇技淫巧

电商下单在普通压力下,一个队列就能解决问题,但是当你面临每秒几十万单的时候,如何让这些订单真正地下单成功,才是最需要解决的问题,这个数字就是“系统容量”。队列是无法提升系统的绝对容量的,那该怎么办呢?

继续找东西和信息之神交换:过去的时间换现在的时间。

在大促之前,先把订单生成好,然后用户下单时直接写入用户信息:不需要执行“检查库存”这个单点操作了,负载低了很多。当初想出这个方法的人实在是太机智了。

现实世界中的削峰

现实世界中,一个一百万 QPS 的电商系统,真正需要触达到数据库的 QPS 其实是没有 500 万那么多的,在削峰的操作下,200 万 QPS 的 PolarDB 集群在 Redis 集群的配合下,是可以顶住 100 万 API QPS 的。史上流量最大的那一年双 11,每秒订单创建最大值仅为 58.3 万笔,这已经是这个地球上的最高记录了。

但是,现实世界中,一切都要讲 ROI(收益成本之比)的,搞一套顶配的 PolarDB 集群确实可以顶住巅峰时期一百万 QPS,但是你老板看着账单肯定会肉痛,那,该如何省钱呢?

答:站在地球表面

阅读数:4949      字数:1296 最后更新:2023-10-26 23:42:03