高并发系统设计:从理论到实践

向量检索学徒
2025-12-19 06:38
阅读 642

凌晨5点,咖啡还没凉,我盯着屏幕上那行 panic: too many open files 的报错,心里一万只羊驼奔腾而过。上周五晚上,产品经理突然甩过来一个“小需求”:下周上线前,系统要支持每秒10万请求的压力测试——理由是“隔壁团队双11扛住了,我们也不能输”。

说实话,半年前我还是个坚定的“AI写代码反对者”。总觉得代码这东西,没亲手敲过、没被线上炸过、没在凌晨三点 debug 过,就不算真正掌握。但最近边刷 LeetCode 边准备跳槽,实在扛不住面试官灵魂拷问:“你做过高并发系统吗?怎么设计的?” 于是被迫从《分布式系统原理》啃起,一路摸爬滚打,居然真香了。

今天这篇,不讲大道理,就说说我怎么用 Go 搞定一个高并发下单系统,顺便聊聊为什么最后放弃了 Java + Spring Cloud 那套“全家桶”。


起因:不是我想卷,是业务逼的

我们团队负责的是一个电商秒杀模块。去年双11,系统直接崩了,DB 连接池打满,Redis 被打穿,运维大哥半夜打电话骂街。今年老板下了死命令:必须支持 10w QPS,延迟 < 50ms

老架构是 Java 写的,Spring Boot + MySQL + Redis,单体部署。别说 10w,连 1w QPS 都稳不住。领导拍板重构,技术选型让我牵头(其实就是背锅)。

我第一反应是继续用 Java——毕竟团队熟。但一算账:要上微服务、熔断、限流、异步队列……光 Spring Cloud Alibaba 一堆组件就能把我绕晕。而且 JVM GC 停顿在高并发下太不可控,上次 Full GC 直接卡了 2 秒,用户都以为页面死了。

这时候,我翻了翻 GitHub 上几个高星项目,比如 go-kratosgo-zero,清一色 Go 写的,性能数据亮眼得离谱。再一看字节、B站、腾讯的开源项目,Go 几乎成了高并发场景的默认选项。

行吧,那就试试 Go。反正跳槽简历上也能写“主导高并发系统重构”,多香。


技术选型:为什么是 Go?

先说结论:Go 的轻量级 goroutine + CSP 并发模型,在 I/O 密集型场景下碾压线程模型

维度 Java (Spring Boot) Go
启动速度 几秒到十几秒 < 100ms
内存占用 单实例 > 500MB 单实例 ~50MB
并发模型 线程(1:1) goroutine(M:N)
GC 停顿 可达数百 ms 通常 < 1ms
部署复杂度 需要 JVM、依赖管理复杂 静态编译,单二进制文件

最打动我的是 goroutine 的开销极低。一个 goroutine 初始栈只有 2KB,而 Java 线程默认 1MB。10w 并发,Java 得开 10w 线程?内存直接爆掉。Go 却能轻松 hold 住。

再加上 Go 的 channel 和 select,写异步逻辑简直丝滑。不用回调地狱,不用 CompletableFuture 嵌套三层,代码可读性拉满。


架构设计:三层防线,层层削峰

我们的目标很明确:不让任何一个请求直接打到数据库。于是搞了个三层防御体系:

  1. 接入层:Nginx + 限流
  2. 服务层:Go 微服务 + 本地缓存 + Redis 队列
  3. 数据层:MySQL 分库分表 + 异步落库

第一层:Nginx 限流兜底

先用 Nginx 做粗粒度限流,防住恶意刷单:

http {
    limit_req_zone $binary_remote_addr zone=order_limit:10m rate=100r/s;
    
    server {
        location /create_order {
            limit_req zone=order_limit burst=200 nodelay;
            proxy_pass http://order-service;
        }
    }
}

别小看这一步,上线第一天就挡掉了 30% 的垃圾流量。

第二层:Go 服务层 —— 真正的战场

核心逻辑用 Go 重写。关键点有三个:

1. 前置校验 + 本地缓存

用户信息、商品库存这些高频读数据,先查本地缓存(用 bigcache),减少 Redis 压力:

// 本地缓存 10 秒,避免 Redis 成瓶颈
var userCache = bigcache.NewBigCache(bigcache.DefaultConfig(10 * time.Second))

func getUser(userID string) (*User, error) {
    if data, err := userCache.Get(userID); err == nil {
        var u User
        json.Unmarshal(data, &u)
        return &u, nil
    }
    // 回源查 DB 或 Redis...
}

2. Redis 队列削峰

下单请求不直接处理,而是推入 Redis Stream(比 List 更可靠):

func CreateOrder(ctx context.Context, req *OrderReq) error {
    // 校验通过后,入队
    _, err := redisClient.XAdd(ctx, &redis.XAddArgs{
        Stream: "order_queue",
        Values: map[string]interface{}{
            "user_id": req.UserID,
            "sku_id":  req.SKU,
            "ts":      time.Now().Unix(),
        },
    }).Result()
    if err != nil {
        return fmt.Errorf("push to queue failed: %v", err)
    }
    return nil // 立刻返回,用户体验快
}

3. 消费者批量处理

后台起多个 goroutine 消费队列,批量写 DB:

func startConsumer() {
    for i := 0; i < 10; i++ { // 10 个消费者
        go func() {
            for {
                msgs, err := redisClient.XRead(ctx, &redis.XReadArgs{
                    Streams: []string{"order_queue", "0"},
                    Count:   100, // 一次最多取 100 条
                    Block:   1000 * time.Millisecond,
                }).Result()
                if err != nil || len(msgs) == 0 {
                    continue
                }
                batchProcess(msgs) // 批量插入 DB
                // ACK 消息(简化版)
            }
        }()
    }
}

这样,前端 10w QPS,后端可能只需要 1k TPS 就能消化完。


数据库:别让 MySQL 成短板

即使做了队列削峰,DB 仍是瓶颈。我们做了两件事:

  1. 分库分表:按 user_id hash 分 16 库,每库 64 表。
  2. 异步 Binlog 同步:用 Canal + Kafka 把订单数据同步到 ES,供查询用。

接口设计也讲究:写接口只返成功/失败,不返完整订单。查询走单独的 read service,彻底读写分离。


上线那天,我手抖了

压力测试跑起来那一刻,我心跳加速。10w QPS 打进来,监控面板上 CPU 稳在 60%,内存 200MB,P99 延迟 38ms。

运维小哥探头问:“这就完了?没报警?”

我说:“对啊,Go 程序,稳定得很。”

他一脸不信:“Java 那会儿,光 GC 日志就能占满一个屏幕。”


总结:真香警告

这次重构让我彻底扭转了对 Go 的偏见。它不是玩具语言,而是为云原生和高并发而生的利器

如果你也在准备跳槽,或者被高并发需求折磨,我强烈建议你:

  • 别死磕 Java 全家桶,Go 的生态已经足够成熟;
  • 善用 GitHub,很多轮子(如 go-zero)直接集成限流、熔断、链路追踪;
  • 高并发的核心不是技术多牛,而是“削峰填谷”的思路——让系统忙而不乱。

最后吐槽一句:产品经理上周又提新需求了,说要加“AI 推荐下单”。我笑了笑,心想:这次,或许真该让 AI 帮我写点代码了。

(完)

附:学习资源推荐

  • GitHub 项目:go-zero(自带高并发最佳实践)
  • 书籍:《Go 语言高并发与微服务实战》
  • 工具:wrk(压测)、pprof(性能分析)

别卷了,早点下班。毕竟,代码跑得再快,也快不过 deadline。

评论 0

最热最新
暂无评论
匿名用户Lv.1
0
影响力
0
文章
0
粉丝