当前位置: 代码网 > it编程>数据库>Redis > Redis + Node 如何支撑百万级并发的实现

Redis + Node 如何支撑百万级并发的实现

2026年09月23日 Redis 我要评论
可以。redis + node.js 支撑百万级并发,核心不是“redis 能不能扛百万”,而是把请求链路做成无状态、异步化、缓存化,并把单机瓶颈拆到多个实例。一个典型架构可以

可以。redis + node.js 支撑百万级并发,核心不是“redis 能不能扛百万”,而是把请求链路做成无状态、异步化、缓存化,并把单机瓶颈拆到多个实例。

一个典型架构可以是:

                    ┌──────────────┐
                    │   cdn / waf  │
                    └──────┬───────┘
                           │
                    ┌──────▼───────┐
                    │ load balancer│
                    └──────┬───────┘
                           │
          ┌────────────────┼────────────────┐
          ▼                ▼                ▼
     node.js #1       node.js #2       node.js #n
     stateless        stateless        stateless
          │                │                │
          └────────────────┼────────────────┘
                           │
                ┌──────────▼──────────┐
                │    redis cluster    │
                │  shard 1 ... shard n│
                └──────────┬──────────┘
                           │
                ┌──────────▼──────────┐
                │ mysql / postgresql  │
                │ read replica / shard│
                └─────────────────────┘

1. node.js:不要让单进程成为瓶颈

node.js 本身适合大量 i/o 并发,但单个 node 进程不能简单理解成能处理百万连接

通常做法:

百万客户端连接
       ↓
load balancer
       ↓
100 × node.js instances
       ↓
redis cluster

例如:

import http from 'node:http';
const server = http.createserver(async (req, res) => {
  const data = await redis.get(`user:${req.userid}`);
  res.end(data ?? '{}');
});
server.listen(3000);

然后通过 kubernetes / docker / pm2 / ecs 等横向扩容。

关键原则:

  • node 服务无状态
  • 不在进程内保存用户 session
  • 不依赖本地内存作为唯一数据源
  • 不做同步 cpu 密集型任务
  • 长任务放 mq / worker
  • 使用连接池
  • keep-alive
  • 合理设置超时
  • 做好 graceful shutdown

2. redis:单机 redis ≠ 百万级架构

这是最容易踩坑的地方。

如果你说:

“我启动一个 redis,然后 node.js 连接它,能不能百万并发?”

通常答案是:不能直接这么设计。

应该考虑:

                redis cluster
        ┌────────┬────────┬────────┐
        │shard 1 │shard 2 │shard 3 │
        │master  │master  │master  │
        └───┬────┴───┬────┴───┬────┘
            │         │        │
          replica   replica  replica

redis cluster 根据 key 做分片:

user:10001 → shard 1
user:10002 → shard 2
user:10003 → shard 3
...

这样才能把:

100 万 qps

拆成:

shard 1 → 20 万
shard 2 → 20 万
shard 3 → 20 万
shard 4 → 20 万
shard 5 → 20 万

具体数字当然需要根据机器 cpu、内存、value 大小、命令类型和网络情况压测,不能简单按节点数线性估算。

3. node → redis 不要创建大量连接

一个非常重要的误区:

100 万用户
=
100 万 redis tcp 连接

完全不是这么回事。

应该是:

100 万客户端
      ↓
几百/几千个 node 实例
      ↓
每个 node 使用 redis connection pool
      ↓
redis cluster

例如单个 node 实例可能维持有限数量的 redis 连接,而不是每个用户创建一个连接。

4. 缓存设计比 redis 本身更重要

例如用户请求:

get /api/user/10086

不要每次:

node
 ↓
mysql
 ↓
返回

而是:

node
 ↓
redis get
 ↓
命中
 ↓
返回

代码类似:

const key = `user:${userid}`;
let user = await redis.get(key);
if (!user) {
  user = await db.query(
    'select * from users where id = ?',
    [userid]
  );
  await redis.set(
    key,
    json.stringify(user),
    { ex: 300 }
  );
}
return json.parse(user);

如果数据库平均只能承受:

20,000 qps

但 redis 可以承受远高于这个数量级的请求,那么大量读请求就不会直接打到数据库。

5. 最危险的问题:缓存击穿

假设:

user:10086

突然过期。

然后同时来了:

100,000 requests

结果:

100,000 node requests
        ↓
redis miss
        ↓
100,000 requests 查询 mysql

数据库直接被打爆。

这就是缓存击穿

可以使用:

single flight / 分布式锁

             redis miss
                 │
       ┌─────────┴─────────┐
       │                   │
   请求 1 获取锁        请求 2~n
       │                   │
       ▼                   │
    查询 db                │
       │                   │
       ▼                   │
   写 redis                │
       │                   │
       └──────────┬────────┘
                  ▼
              返回数据

例如:

const lockkey = `lock:${key}`;
const locked = await redis.set(
  lockkey,
  '1',
  { nx: true, ex: 5 }
);
if (locked) {
  try {
    const data = await loadfromdb();
    await redis.set(key, json.stringify(data), { ex: 300 });
  } finally {
    await redis.del(lockkey);
  }
}

生产环境还要考虑锁 token、续期、异常释放等问题,不能简单把 set nx 当成完整分布式锁方案。

6. 缓存雪崩也必须处理

假设你有:

1,000,000 keys

全部:

ttl = 300

如果大量 key 在同一时间过期:

redis
 ↓
大量 miss
 ↓
db
 ↓
db cpu 100%
 ↓
服务雪崩

不要:

ex = 300

全部固定。

可以加入随机 ttl:

const ttl = 300 + math.floor(math.random() * 60);
await redis.set(
  key,
  json.stringify(data),
  { ex: ttl }
);

让过期时间分散。

7. 热点 key 是百万并发架构里的大坑

例如:

商品 id = 10086

突然:

500,000 qps

全部访问:

product:10086

即使 redis cluster 有 20 个 shard:

product:10086
       ↓
同一个 hash slot
       ↓
同一个 redis shard

这叫热点 key

可以考虑:

product:10086:1
product:10086:2
product:10086:3
...
product:10086:n

或者在 node 本地做极短时间的 l1 cache:

request
   ↓
node l1 cache
   ↓ miss
redis
   ↓ miss
db

例如:

l1:几十毫秒~几秒
l2:redis
l3:db

对于极热、变化不频繁的数据非常有效。

8. 写请求不要全部同步打数据库

假设用户行为:

post /api/like

100 万并发下,如果每个请求都:

node
 ↓
mysql update
 ↓
等待
 ↓
response

数据库很容易成为瓶颈。

可以变成:

client
  ↓
node
  ↓
redis
  ↓
mq
  ↓
worker
  ↓
mysql

例如:

点赞
 ↓
redis incr
 ↓
kafka / redis stream
 ↓
worker 批量处理
 ↓
mysql

于是 web 请求不需要等待数据库事务完成。

9. redis 不应该承担所有事情

比较合理的职责:

数据推荐
sessionredis
登录 tokenredis
热点数据redis
排行榜redis
rate limitredis
分布式锁redis
pub/subredis
持久业务数据mysql/postgresql
大文件oss/s3
日志kafka/log system
大规模异步任务kafka/rabbitmq 等

尤其不要把 redis 当成:

“天下无敌的数据库”

redis 的内存成本很高,而且很多业务数据仍然需要关系数据库提供事务、复杂查询和持久化能力。

10. 限流是百万并发的必需品

百万并发并不意味着:

所有请求都应该进入业务系统。

例如 api:

/api/login
/api/order
/api/payment

必须限流。

redis 可以实现 token bucket / sliding window:

user
 ↓
rate limiter
 ↓
redis
 ↓
允许 → node
拒绝 → 429

例如:

ip:100 req/s
user:50 req/s
api:10,000 req/s
global:1,000,000 req/s

不同维度分别控制。

11. node.js 还要特别注意事件循环

下面这种代码:

app.get('/api/data', (req, res) => {
  const result = heavycalculation();
  res.json(result);
});

如果:

heavycalculation()

耗时 500ms,并且占满 cpu,那么一个 node 进程的事件循环会被阻塞。

结果:

request 1 ──┐
request 2 ──┤
request 3 ──┼── event loop 被卡住
request 4 ──┤
request 5 ──┘

所以 cpu 密集型任务应该考虑:

node
 ↓
worker threads / job queue
 ↓
worker

或者直接拆成独立 worker 服务。

12. 一个比较完整的百万并发架构

如果让我设计一个典型的:

node.js + redis + mysql 百万级并发系统

我会考虑:

                         internet
                            │
                     ┌──────▼──────┐
                     │ cdn / waf   │
                     └──────┬──────┘
                            │
                     ┌──────▼──────┐
                     │ loadbalancer│
                     └──────┬──────┘
                            │
          ┌─────────────────┼─────────────────┐
          │                 │                 │
      node #1           node #2           node #n
          │                 │                 │
          └─────────────────┼─────────────────┘
                            │
                  ┌─────────▼─────────┐
                  │    redis cluster  │
                  │                   │
                  │ shard 1           │
                  │ shard 2           │
                  │ shard 3           │
                  │ ...               │
                  └─────────┬─────────┘
                            │
                 ┌──────────┴──────────┐
                 │                     │
                 ▼                     ▼
             message queue          mysql
                 │               read replicas
                 ▼
              workers

再配:

cdn
+
waf
+
load balancer
+
node.js cluster
+
redis cluster
+
mq
+
mysql read replica
+
monitoring
+
rate limiting
+
circuit breaker
+
autoscaling

13. 真正需要计算的是这几个数字

“百万并发”本身其实不是一个完整的性能指标。

必须区分:

100 万 tcp/websocket 长连接

和:

100 万 rps

完全是两个问题。

例如:

场景 a

1,000,000 长连接
10,000 rps

node.js 非常适合。

场景 b

1,000,000 rps
每次请求 redis get

重点变成:

redis cluster
网络
node 实例数量
请求大小
命令类型
热点 key

场景 c

1,000,000 rps
每次请求都查询 mysql

这时候 redis 也救不了你。

最后给你一个实际落地思路

如果你是准备做真正的百万级并发项目,不要一上来就堆几十台服务器。

建议按这个顺序:

① node.js 单实例压测
        ↓
② redis 单实例压测
        ↓
③ node × n 横向扩容
        ↓
④ redis cluster
        ↓
⑤ 缓存击穿/雪崩/热点 key
        ↓
⑥ db 读写分离
        ↓
⑦ mq 异步化
        ↓
⑧ 限流 + 熔断 + 降级
        ↓
⑨ 全链路监控
        ↓
⑩ 压测到目标 qps

千万不要用“百万并发”直接反推机器数量。 应该先定义目标,例如:

并发连接:1,000,000
目标 qps:200,000
p99:< 100ms
redis 命中率:> 95%
单请求平均响应:20ms
可用性:99.99%

然后根据压测结果倒推 node、redis、数据库和网络规模。

如果你愿意,我也可以进一步给你一套**“node.js + redis cluster + mysql 实现 100 万并发”的生产级项目架构**,包括 docker/k8s、redis cluster、node.js 代码、限流、缓存击穿、mq、数据库分库分表以及压测方案

到此这篇关于redis + node 如何支撑百万级并发的实现的文章就介绍到这了,更多相关redis node百万级并发内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com