171. 生产经验:真实生产环境下的数据库机器配置如何规划?

1、当你了解数据库的架构原理之后,就该了解一下自己数据库的规划

相信大家对数据库的整体架构原理都有一定的了解,当我们初步了解了数据库的架构设计原理后,接着其实应该了解的第一件事,就是我们平时在工作中,如何规划生产环境下的数据库。因为我想很多人如果平时主要是负责一些没什么并发量,用户量也就几十个或者几百个人的系统,那么根本就不会去关注数据库的规划这件事情。

对很多Go工程师而言,要不然是自己找一台linux机器装一个MySQL,然后就让自己的系统连接上去直接就开始使用了,要不然就是让DBA或者运维工程师帮自己去找一台机器装一个MySQL或者Oracle,然后自己就可以直接使用了。

但是大家还是需要有较为专业化的数据库使用经验才能在技术深度上走的更远,包括数据库的整体架构原理,还有就是如何规划生产环境下的数据库,包括当你有一个生产库之后,要做的事情就是设计压测方案,包括对你的数据库进行压测,包括对你的 数据库部署可视化监控系统,等等。

当你做好这一系列的事情之后,接着才应该是开发你的Go系统,去操作你的数据库,实现各种各样的业务功能和逻辑。

2、生产数据库一般用什么配置的机器?

现在我们来看第一个问题,假设你在生产环境中需要部署一个数据库,此时首先你就需要一个机器来部署这个数据库。那么我们要考虑的事情就是,部署一个生产环境的数据库,一般需要什么样配置的机器呢?

接下来我们将会给大家说一些我们的经验值,直接告诉大家什么样配置的机器部署的MySQL数据库,大致适合多高的并发访问量

当你了解这个经验值之后,未来当你在负责系统的开发,申请数据库的时候,你就知道生产环境下的数据库大致需要什么样 机器配置了,大致可以抗下多少并发访问了。

首先我们先明确一点,如果你负责的系统就是一个没什么并发访问量,用户就几十个人或者几百个人的系统,那么其实你选择 什么样的机器去部署数据库,影响都不是很大,哪怕是你用我们自己平时用的个人笔记本电脑去部署一个MySQL数据库,其实也能支撑那种低并发系统的运行。

因为那种系统可能每隔几分钟才会有一波请求发到数据库上去,而且数据库里一张表也许就几百条、几千条或者几万条数据, 数据量很小,并发量很小,操作频率很低,用户量很小,并发量很小,只不过可能系统的业务逻辑很复杂而已。对于这类系统的数据库机器选型,就不在我们的考虑范围之内了。

我们主要关注的是有一定并发量的互联网类的系统,对数据库可能会产生每秒几百,每秒几千,甚至每秒上万的并发请求量,对于这类场景下,我们应该选择什么样的机器去部署数据库,才能比较好的抗下我们的系统压力。

3、普通的Go应用系统部署在机器上能抗多少并发?

通常来说,根据我们的经验值而言,Go应用系统部署的时候常选用的机器配置大致是2核4G和4核8G的较多一些,数据库部署的时候常选用的机器配置最低在8核16G以上,正常在16核32G

那么以我们大量的高并发线上系统的生产经验观察下来而言,一般Go应用系统部署在4核8G的机器上,每秒钟抗下500左右的并发访问量,差不多是比较合适的,当然这个也不一定。因为你得考虑一下,假设你每个请求花费1s可以处理完,那么你一台机器每秒也许只可以处理100个请求,但是如果你每个请求只要花费100ms就可以处理完,那么你一台机器每秒也许就可以处理几百个请求。

所以一台机器能抗下每秒多少请求,往往是跟你每个请求处理耗费多长时间是关联的,但是大体上来说,根据我们大量的经验观察而言,4核8G的机器部署普通的Go应用系统,每秒大致就是抗下几百的并发访问,从每秒一两百请求到每秒七八百请求,都是有可能的,关键是看你每个请求处理需要耗费多长时间。

4、高并发场景下,数据库应该用什么样的机器?

对于数据库而言,我们刚才也说过了,通常推荐的数据库至少是选用8核16G的机器,甚至是16核32G的机器更加合适一 些。

因为大家要考虑一个问题,对于我们的Go应用系统,主要耗费时间的是Go系统和数据库之间的网络通信。对Go系统自己而言,如果你仅仅只是系统内部运行一些普通的业务逻辑,纯粹在自己内存中完成一些业务逻辑,这个性能是极高极高的。

对于你Go系统接收到的每个请求,耗时最多的还是发送网络请求到数据库上去,等待数据库执行一些SQL语句,返回结果给你。

所以其实我们常说你有一个Go系统压力很大,负载很高,但是其实你要明白一点,你这个Go系统其实主要的压力和复杂都是集中在你依赖的那个MySQL数据库上的!

因为你执行大量的增删改查的SQL语句的时候,MySQL数据库需要对内存和磁盘文件进行大量的IO操作,所以数据库往往是负载最高的!

而你的Go系统一般并不需要你去直接大量的读写本地文件进行耗时的IO操作吧?是不是,想必做过Go开发的朋友一下子就会想明白这个道理。

所以往往对一个数据库而言,都是选用8核16G的机器作为起步,最好是选用16核32G的机器更加合适一些,因为数据库需要 执行大量的磁盘IO操作,他的每个请求都比较耗时一些,所以机器的配置自然需要高一些了。

然后通过我们之前的经验而言,一般8核16G的机器部署的MySQL数据库,每秒抗个一两千并发请求是没问题的,但是如果你 的并发量再高一些,假设每秒有几千并发请求,那么可能数据库就会有点危险了,因为数据库的CPU、磁盘、IO、内存的负载 都会很高,弄不好就会数据库压力过大就会宕机。

对于16核32G的机器部署的MySQL数据库而言,每秒抗个两三千,甚至三四千的并发请求也都是可以的,但是如果你达到每秒上万请求,那么数据库的CPU、磁盘、IO、内存的负载瞬间都会飙升到很高,数据库也是可能会扛不住宕机的。

所以这就是对于数据库,我们一般推荐选用的机器的配置,以及他大致可以抗下多高的并发请求量的经验分享。

另外对于数据库而言,如果可以的话,最好是采用SSD固态硬盘而不是普通的机械硬盘,因为数据库最大的复杂就在于大量的 磁盘IO,他需要大量的读写磁盘文件,所以如果能使用SSD固态硬盘,那么你的数据库每秒能抗的并发请求量就会更高一些。

5、思考题

给大家一个小的思考题:假设你开发的Go系统部署在一台4核8G的机器上,那么我们假设这个Java系统处理一个请求非常非常快,每个请求只需要0.01ms就可以处理完了,那你觉得这一台机器部署的Go系统,可以实现每秒抗下几千并发请求吗?可以实现每秒抗下几万并发请求吗?

简短回答是: 对于这种每个请求只需要 0.01ms (0.00001秒) 处理的极端简单场景,每秒几千并发是轻而易举的,甚至每秒几万并发也完全有可能达到。

下面我们来详细计算和解释为什么。

1. 核心计算:理论上的QPS上限

我们先忽略所有系统开销,计算一下纯CPU的理论处理能力。

  • 单个请求处理时间: 0.01 ms = 0.00001 秒

  • 单个核心(core)每秒能处理的请求数 (QPS): 1秒 / 0.00001秒/请求 = 100,000 QPS

  • 4个核心(4核)的理论总QPS上限: 4核心 * 100,000 QPS/核心 = 400,000 QPS

这个 40万 QPS 是一个在理想环境下的绝对上限。它假设:

  1. CPU 100%忙于处理业务逻辑,没有任何空闲。

  2. 没有锁竞争、没有GC开销、没有系统调用开销。

  3. 请求的到达是绝对均匀的,并且系统能立即调度处理。

显然,现实世界中不可能达到这个数字,但它告诉我们,这个任务的CPU负载非常轻。

2. 现实中的瓶颈在哪里?

对于Go语言编写的系统,在达到几千/几万并发时,主要的瓶颈通常不在业务逻辑CPU计算上,而是在以下几个方面:

a. 网络I/O
这是最可能的首个瓶颈。 每个请求都需要通过TCP/IP协议栈,涉及系统调用(read, write, epoll等)。

Go的 net/http 服务器和 net 包虽然高效,封装了epoll(如Linux下的epoll),但这些系统调用本身、内核态和用户态的数据拷贝是有开销的。

如果使用HTTPS,TLS加解密的CPU开销会远大于你设定的0.01ms业务逻辑。

b. 内存与垃圾回收(GC)
即使每个请求只分配极少的内存(比如几个小对象),在数万QPS下,每秒分配的总内存量也会很大。

Go的GC是为了低延迟设计的,但在高分配速率下,GC会频繁触发,占用宝贵的CPU时间片,从而挤占业务处理能力。这会使得实际QPS远低于理论值。

c. 调度器开销
Go的GMP模型非常高效,但在数万个goroutine同时运行和切换时,调度器本身的管理开销(如寻找可运行的goroutine、在M(线程)上切换G等)会变得显著。

d. 外部依赖
如果你的Go系统需要访问数据库、缓存(如Redis)或其他微服务,那么瓶颈会立刻转移到这些I/O操作上。它们的延迟(通常是毫秒甚至几十毫秒级)会远远超过0.01ms,成为系统的决定性瓶颈。不过在你的问题中,我们假设业务处理本身极快,暂不考虑此外部因素。

3. 量化估算:几千 vs 几万

现在我们结合现实开销来估算:

  • 每秒几千并发 (例如 1,000 - 9,000 QPS)

    • 这对于一台4核8G的机器和如此简单的业务逻辑来说,是 “轻松” 级别的。

    • 在这个量级,Go的网络库和调度器游刃有余,GC压力很小。系统负载可能不到5%。完全可以稳定运行。

  • 每秒几万并发 (例如 10,000 - 50,000+ QPS)

    • 完全有可能实现,但已经开始触及系统资源的边界。

    • 我们取一个中间值,比如 30,000 QPS。

    • 此时,每个请求的总耗时(网络 + 业务 + GC + 调度)可能远大于0.01ms。假设平均总耗时达到0.1ms(已经是优化得很好的情况了),那么需要 30,000 QPS * 0.0001秒 = 3个核心 的持续算力。这还在4核的能力范围内。

    • 但此时,GC会开始成为明显的影响因素。你可能需要优化代码,减少内存分配,并调优GOGC参数。

    • 网络栈和文件描述符的数量也需要检查系统的内核参数(如 net.core.somaxconn)。

  • 接近或超过100,000 QPS

    • 这会非常困难。系统大部分时间可能花在了处理网络I/O、GC和调度上,而不是你的业务逻辑。

    • 要达到这种级别,通常需要极致的优化,例如:

      • 使用更高效的序列化方式(如protobuf代替JSON)。

      • 使用连接池、对象池来减少GC压力。

      • 甚至考虑使用 syscall 包绕过Go的标准库进行更低层的网络操作(但这非常复杂且不推荐一般情况使用)。

结论

  • 几千并发? 绝对可以。 对系统来说是小菜一碟。

  • 几万并发? 很有可能。 在代码编写良好、没有外部瓶颈、且对Go的运行时进行适当调优的情况下,实现2-5万QPS是合理的目标。但要达到5万以上,则会面临挑战,需要深入的性能分析和优化。

最终,一个系统的性能不仅仅取决于CPU。 对于你描述的这个场景,瓶颈更可能出现在 网络I/O栈、内存管理(GC)和操作系统限制 上,而不是那0.01ms的业务计算。通过压力测试(例如使用 wrk 或 hey 工具)并配合 pprof 进行 profiling,是确定真实性能和瓶颈所在的最佳方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值