人列计算机
《三体》中,刘慈欣设计了一个用人进行二进制运算的计算机,应用了三千万名士兵(晶体管):
- 计算机名:秦一号
-
CPU:秦始皇最精锐的五个军团
- 挥动旗号进行二进制运算
- 用三个士兵来组成与门、或门、与非门、或非门、异或门、同或门和三态门,又用两个士兵组成了非门
- 将这些根本部件组合起来,形成了计算阵
- 内存:由文化程度较高的人组成,每个人挥动多个色彩的旗号,能够代替 20 个挥动单色旗号的人
- 硬盘:三百万文化程度较高的人(据说是上次坑儒留下来的)
- 显示阵列:至多配有红色和绿色像素单元(双色显示阵列)
-
保护部件:一组骑兵
- 传输信号
- 解决“故障”士兵
- 由秦始皇最精锐的骑兵团形成
- 保护形式:更换出错部件
一提到高并发,很多人的第一反馈都能够演绎为以下两种状况:
1. 过程间通信(IPC)、共享内存、管道、队列、事件:这是学院派
2. 内存缓存、音讯队列、分库分表、NoSQL、ES 搜寻:这是实战派
其实,高并发之路,无论是学院派还是实战派,甚至是刘慈欣设计的人列计算机,其背地的哲学原理都是一样的。如果你问人列计算机和高并发有什么关系?依照下面的设计,最多一万名士兵就够了,为什么须要三千万呢?还不是为了进步性能。
其实,高并发的哲学原理早就暗藏在了古代计算机的根底构造之中,感兴趣的欢送去看我的《性能之殇(二)– 分支预测、流水线与多核 CPU》¹。
本文指标
下面只是我的喃喃私语,上面咱们进入正题。
本文的指标是在我无限的认知范畴内,讨论一下高并发问题背地暗藏的一个哲学原理。咱们将从动静拆散讲起,一步步深刻 Apache、Nginx、epoll、虚拟机、k8s、异步非阻塞、协程、利用网关、L4/L7 负载均衡器、路由器(网关)、交换机、LVS、软件定义网络(SDN)、Keepalived、DPDK、ECMP、全冗余架构、用户态网卡、集中式存储、分布式存储、PCI-E 5.0、全村的心愿 CXL、InnoDB 三级索引、内存缓存、KV 数据库、列存储、内存数据库、Shared-Nothing、计算存储拆散、Paxos、微服务架构、削峰、基于地理位置拆分、高可用等等等等。并最终基于地球和人类社会的根本属性,设计出能够服务地球整体人类的高并发架构。
先说论断,这个哲学原理就是:找出单点,进行拆分
。
筹备工作
性能问题要靠架构解决
在开展这个哲学原理前,咱们须要先明确一下高并发问题的解决思路:性能问题要靠架构解决。
首先,在架构上动刀是最简略的,也是最容易取得收益的。其次,即使是真的去做单个资源的性能优化,例如 MySQL 单机性能优化(软件优化)、x86 CPU 多核性能晋升(硬件优化),拆到宏观来看,也是在做架构优化:
没有银弹
就是计算机世界的第一准则,你想取得收益,总得拿出一些货色,和 信息之神
替换。
咱们探讨“哪个”高并发?
本文探讨的是“web 服务高并发”问题,典型场景为电商秒杀:同一个时刻,数万人抢同一个低价商品,会给零碎的每一个层面都造成显著的性能瓶颈,这种场景的集大成者,就是每年的双 11。
一个小指标
找出单点,进行拆分
,就是将每一个大单点都拆成一个小单点 + 多资源并行的模式。
在解决高并发问题的过程中,咱们会一直地遇到新的单点:web server、单个操作系统、虚拟化 / 容器技术、编程语言运行架构、网络、UNIX 过程模型、数据库等。每遇到一个单点,咱们都要见招拆招,应用 架构
工具拆掉它。计算机的虚拟化水平十分高,简直每个单点都能够持续往下拆。
接下来大家就跟着我一起,一步一步将零碎性能的下限从单机 100 QPS 晋升到 1,000,000(一百万)QPS。
文章列表
- 找出单点,进行拆分(本文)
- Apache 的性能瓶颈与 Nginx 的性能劣势
- 基础设施并发:虚拟机与 Kubernetes(k8s)
- 暗藏在语言背地的魔鬼:运行架构为何会成为性能瓶颈
- 拆分网络单点(上):利用网关、负载平衡和路由器(网关)
- 拆分网络单点(下):SDN 如何代替百万人民币的负载平衡硬件(网关、LVS、交换机)
- 最难以解决的单点:数据库以及它背地的存储
- 将 InnoDB 剥的赤身露体:B+ 树与 Buffer Pool
- 细数四代分布式数据库并拆解 TiDB 和 OceanBase(主从、中间件、KV、计算与存储拆散、列存储、CAP 定理)
- 实践有限容量:站在地球表面
找出第一个单点
大部分零碎都是从单个虚拟机开始的,原始的资源可能只有 1 核 2G,你装置了一个 Apache,一个 MySQL,把代码部署下来,这个零碎就开始对外服务了。如果零碎用户数量减少了,你会发现,CPU 满了,这个时候,咱们第一个应该拆的就是动态流量。
动静拆散
大略是在 2013 年,我用从同学那里买的二手 MacBook Pro 跑过 Apache 和 Nginx 的性能测试,在本机拜访同一张 jpg 图片的状况下,Apache 的 QPS 为 2 万出头,而 Nginx 则超过 8 万,四倍性能。
所以,如果你还在用 Apache 承载所有流量,在后面加一个 Nginx 就能显著升高 CPU 占用率,大幅晋升零碎性能。如果你再利用云服务商把这些动态资源用 CDN 来承载,你的动态资源压力还能再升高 90%。
动静拆散当前,CPU 又满了,该怎么办呢?这个时候就须要把数据库拆出去了。
最适宜独立部署的软件:数据库
如果利用代码和数据库跑在一个零碎上,压力略微大一点,很容易呈现“债股双杀”的场面:MySQL 的响应变慢,利用代码就须要更长时间的期待,又要耗费更多的 CPU 资源,从而造成“内卷”和“踩踏”。只有你的零碎不是用户极其少,或者你们公司极其抠,把数据库独立部署的收益都是要高于投入的:1 核 2G 的虚拟机就够 MySQL 跑到 200 QPS 了,配合缓存撑持一个日 PV 100 万的小零碎应该够了。
我的理论教训
进击的爬虫
2017 年,我保护的一个 SEO 网站忽然遭逢大量爬虫的袭击:因为这个网站领有数百万个内容页面,页面内也有着大量的“相似文章举荐”,在只依附 MySQL like
语句的状况下,单个页面的返回工夫长达 300-500ms。一天两万的实在用户 UV 对系统的压力并不大,但这些爬虫不讲武德,上来就是 100 QPS,过后 1 核 2G 的虚拟机和 1 核 1G 的 MySQL 可遭了殃了,齐全顶不住。
这些爬虫并不是正规大厂的爬虫,而是采集机器人,因为领有海量代理 ip,对网站造成了 DDOS 态势,没法应用惯例伎俩封禁,只能想方法抗住。
我首先做的,就是将动态资源全副 CDN 化,间接让 CPU 占用率升高了一半。而后就开始着手晋升零碎性能:
- 应用 ElasticSearch 提供“相似文章举荐”,将每个页面的响应工夫压缩到了 200ms
- 晋升数据库性能:减少索引,减少 Redis 缓存,应用定时工作刷新文章总数而不是实时计算,将响应工夫压缩到了 120ms
- 拜访 ES 的 HTTP 申请进行并行化:尽管 PHP 是一种阻塞语言,然而一次性发送多个 HTTP 申请的能力还是有的,均匀每个页面有五次申请,每次 15ms,并行化当前从 15ms*5 缩小到了 25ms,最终将均匀响应工夫压缩到了 70ms
同时,服务器和数据库也进行了计算资源的扩容,减少到了 2 核 4G 的虚拟机和 2 核 4G 的 MySQL,最终顶住了每天 200 万次页面拜访的冲击,比照之下,实在用户 PV 每天只有十万左右。
这个时候可能有人会问了,既然是内容网站,为什么不动态化呢?因为数据量太大了,500 万个页面,一个页面 100KB,就是 476GB 的磁盘容量,这个量级太夸大了,不如做性能优化硬抗了,这么多动态资源的治理和刷新反而是个更大的问题。在百万量级下,数据库相对是更好的数据存储解决方案,远比本人管理文件要更简略更稳固。
即使我做了那么多,还是不乏有一些爬虫愣头青在学习了 swoole 和 go 协程之后,对我的网站动员数千 QPS 的死亡冲锋,这个时候再怎么性能优化都是没用的,这时就须要应用倒数第二个工具:限流。
我做了三道限流关卡才最终顶住采集机器人 DDOS:
- 针对单个 ip 做申请频率限度
- 针对整个 /24 ip 段做申请频率限度(很多爬虫采纳同一段内的多个 ip 绕过限流)
- 针对每个 UA 做申请频率限度
在这三板斧使进去当前,天下太平了,网站再也没有被忽然发动的死亡冲锋搞挂过。
对了,既然限流是倒数第二个工具,必定有人好奇最初一个工具是什么?那就是熔断,熔断属于零碎鲁棒性工具,是善后用的,咱们最初一篇文章还会再提一嘴。
本文由 mdnice 多平台公布