高并发系统设计:我在腾讯系公司被逼出来的实战心得

队列在排队
2026-01-14 00:46
阅读 1205

上周五晚上十一点,我还在公司死磕一个线上接口超时的问题。婚礼请柬刚发出去没多久,婚期就在三个月后,结果这会儿还得盯着 Grafana 上那条突兀的 99 分位延迟曲线——从平时的 80ms 突然飙到 1.2s。产品经理在群里@我说:“这个接口是用户下单的关键路径,双11前必须稳住!” 我一边回“收到”,一边默默把咖啡续上,心里只想问:谁说程序媛不能又搞技术又备婚?

我是坐标深圳的后端开发,目前在一家腾讯系创业公司做核心交易系统。平日里写 Python、调性能、怼需求,周末还要试婚纱、选婚庆、和婚策师斗智斗勇。最近因为想跳槽(没错,结婚前先涨薪),开始疯狂刷高并发相关的面试题,结果发现光背八股文根本不够——真正的挑战,永远来自生产环境那一行行不受控的流量。

今天就来聊聊高并发系统设计这件事。不讲教科书定义,只说我在项目里踩过的坑、掉过的头发,以及怎么用 Python 搞定一场真实的流量洪峰。


流量来了,系统崩了?别慌,先搞清楚“高并发”到底高在哪

很多人一听到“高并发”就想到 Redis + Kafka + Nginx 三件套,但其实高并发的核心不是堆中间件,而是理解业务瓶颈在哪

我们系统有个典型的运营活动场景:每周五晚8点限量秒杀。去年双11期间,预估 QPS 是 5k,结果真实峰值冲到 23k!数据库连接池直接打满,MySQL CPU 飙到 100%,API 返回全是 502。

当时我真的想砸电脑。

后来复盘发现,问题出在读写耦合:前端请求一进来,先查库存(SELECT),再扣减(UPDATE),整个过程串行且强依赖 DB。更糟的是,库存表没加缓存,每次都要穿透到 MySQL。

于是我们做了第一轮优化:读写分离 + 缓存前置

# 伪代码:用 Redis 缓存库存,避免每次查 DB
import redis

r = redis.Redis(host='cache-cluster', port=6379, decode_responses=True)

def deduct_stock(product_id: str, amount: int) -> bool:
    # 先尝试从 Redis 扣减
    stock_key = f"stock:{product_id}"
    current = r.get(stock_key)
    
    if current is None:
        # 缓存未命中,回源 DB(这里要加分布式锁防击穿)
        with db_lock(product_id):
            stock = db.query("SELECT stock FROM products WHERE id = %s", product_id)
            r.setex(stock_key, 300, stock)  # 缓存5分钟
            current = stock
    
    if int(current) >= amount:
        # Redis 原子扣减
        result = r.decrby(stock_key, amount)
        if result >= 0:
            # 异步更新 DB(通过消息队列)
            send_to_kafka("update_stock", product_id, -amount)
            return True
        else:
            # 超卖了,回滚
            r.incrby(stock_key, amount)
            return False
    return False

这段代码的关键点:

  • 缓存兜底:避免每次请求都打 DB
  • 原子操作:Redis 的 DECRBY 保证线程安全
  • 异步持久化:DB 更新走 Kafka,不阻塞主流程

上线后,QPS 从 23k 压到 500 左右打 DB,MySQL 压力骤降。Grafana 曲线终于平滑了,我也能安心去试婚纱了(虽然那天还是迟到了)。


面试题挑战:如何防止超卖?别只说“加锁”

说到超卖,这简直是高并发面试的必考题。我面过几家大厂,面试官最爱问:“你用什么方案防止超卖?”

很多人脱口而出:“加 Redis 分布式锁!”
但你真敢在秒杀场景用 SETNX 加锁吗?锁竞争会导致大量请求排队,响应时间爆炸,用户体验直接崩盘

我们的做法是:无锁化 + 限流 + 队列削峰

第一步:前端限流 + 验证码

运营同学一开始反对:“加验证码会影响转化率!”
但事实是:不加验证码,黄牛脚本就把库存抢光了,真实用户根本抢不到。最后我们折中:前 100 名免验证,后续触发图形验证码。转化率反而提升了(因为真实用户留住了)。

第二步:服务层令牌桶限流

用 Python 的 redis-py 实现令牌桶:

def acquire_token(user_id: str, rate: int = 10, capacity: int = 20) -> bool:
    """
    每用户每秒最多10次请求,桶容量20
    """
    key = f"rate_limit:{user_id}"
    now = time.time()
    pipe = r.pipeline()
    pipe.zremrangebyscore(key, 0, now - 1)  # 清理过期令牌
    pipe.zcard(key)                          # 当前令牌数
    pipe.zadd(key, {now: now})               # 添加新令牌
    pipe.expire(key, 2)
    results = pipe.execute()
    
    current_tokens = results[1]
    return current_tokens <= capacity

第三步:请求入队,异步处理

所有秒杀请求先进 Kafka,后端消费者按能力消费。这样即使瞬时 10w 请求,系统也能“细水长流”。

方案 吞吐量 超卖风险 用户体验
直接 DB 扣减 差(大量失败)
Redis + 锁 中(延迟高)
缓存 + 队列 + 限流 极低 好(快速响应“排队中”)

运营不懂技术?那就用数据说话

技术人常抱怨运营“乱提需求”,但其实高并发系统的稳定性,离不开运营的配合

比如我们有一次事故:运营临时加了一个“分享得优惠券”活动,结果分享链接没做防刷,黑产用脚本疯狂注册领券,导致用户中心服务 OOM。

后来我们定了规矩:

  • 所有运营活动必须提前一周提技术评审
  • 必须提供预估流量(附历史数据)
  • 关键路径必须有熔断和降级方案

现在每次开需求会,我都会甩出一张压测报告:“你看,如果不限流,DB 会在第 3 秒挂掉。” 运营同学秒懂,再也不敢随便改规则了。


Python 能扛高并发吗?别被偏见耽误了

经常有人吐槽:“Python 不适合高并发,GIL 锁死性能。”

这话对也不对。如果你用 Flask 写个单进程 API 接 1w QPS,那确实不行。但现代 Python 生态早就不止于此了

我们的做法:

  • Web 层:用 Uvicorn + FastAPI(基于 asyncio,异步非阻塞)
  • 任务队列:Celery + Redis Broker
  • 数据库:asyncpg(异步 PostgreSQL 驱动)

关键配置示例(Docker Compose):

# docker-compose.yml
services:
  web:
    image: my-fastapi-app
    command: uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
    environment:
      - WORKERS=4
      - MAX_REQUESTS=1000  # 防内存泄漏
    deploy:
      resources:
        limits:
          memory: 2G

压测结果(4 核 8G 机器):

  • 单 worker:~1200 RPS
  • 4 workers:~4500 RPS(近乎线性提升)

Python 的优势在于开发效率和生态。用 FastAPI 写一个带限流、认证、监控的接口,可能只要 20 行代码。省下的时间,够我去试三次婚纱了好吗!


最后一点真心话:高并发不是炫技,是责任

很多人学高并发是为了面试,为了跳槽涨薪(包括我)。但当你真正负责一个每天百万用户的系统时,你会意识到:高并发设计的本质,是对用户负责

一次超时,可能让用户错过限量球鞋;一次超卖,可能让品牌信誉受损;一次宕机,可能让运营几个月的努力白费。

所以别只盯着 QPS 数字,多问问:

  • 用户最不能忍的是什么?(通常是“一直转圈”)
  • 哪里最容易出事?(往往是第三方依赖)
  • 出事后怎么快速恢复?(要有开关、降级、回滚)

我现在每天上班第一件事,就是看监控大盘。不是怕背锅,而是知道背后有成千上万真实的人在用我们的产品——他们可能正在抢一张演唱会门票,或者给我未来的婚礼众筹礼物呢(好吧,这个是我瞎想的)。


结语:一边写代码,一边筹备婚礼,人生何尝不是高并发?

写这篇文章的时候,婚庆公司刚发来最终流程表,而我的 PR 也刚好被 merge。生活和工作,都是高并发系统——需要缓存(提前准备)、限流(分清优先级)、异步处理(别事事亲力亲为),最重要的是:别让自己成为瓶颈

如果你也在备婚+coding 的路上,欢迎留言交流!顺便问一句:深圳哪家西装定制靠谱?我对象说要穿得像《硅谷》里的 Richard……(救救我)

技术可以学,头发不能少。
高并发不可怕,可怕的是没人帮你 hold 住运营的需求。

评论 0

最热最新
暂无评论
队列在排队Lv.1
0
影响力
0
文章
0
粉丝