Node.js高并发方案

Node.js高并发方案

Node.js高并发方案

集群

Node.js是单线程的,可以利用Cluster模块创建多个子进程来利用多核CPU,子进程共享相同的端口,平均分发请求,提高并发处理能力。

反向代理

常用的反向代理服务器有Nginx和HAProxy。

  • Nginx

使用Nginx作为反向代理服务器,将请求分发给多个Node.js实例。

还可以用Nginx处理静态文件、SSL卸载以减轻Node.js的压力。

  • HAProxy

HAProxy也可以做负载均衡。

消息队列

消息队列的作用有:解耦服务,异步任务处理,缓冲突发流量。

常用RabbitMQ、Kafka。

缓存

内存缓存

将频繁访问的数据写入内存。

可以使用内存数据库Redis、Memcached,将高频访问的数据写入内存数据库以提高响应速度。

HTTP缓存

服务端设置HTTP header的某些字段来减少客户端对服务端的请求,可以降低服务端压力。

  • Cache-Control
  • ETag

数据库优化

读写分离

通过主从复制将数据库读写操作分离,在从库读取,在主库写入。

索引优化

确保查询语句有合适的索引,避免全表扫描。

分库分表(Database Sharding & Table Sharding)

分库

分库就是将数据分散到多个数据库中。

分库又分为垂直分库和水平分库。

  • 垂直分库

根据业务模块的不同,将数据按照业务模块的不同拆分到多个数据库中。优点是不同模块的读写操作互不影响。

比如,在电商系统中,可以将用户模块的数据放在一个数据库中,将订单模块数据放在另一个数据库中。

  • 水平分库

将同一个表的数据按照某种规则拆分到多个数据库中。优点是可以均衡数据量和访问压力。

比如,在电商系统中,将用户表中的数据按照用户ID范围或者哈希值拆分到多个数据库中。

分表

分表就是将一张表的数据分散到多张表中。

分表又分为垂直分表和水平分表。

  • 垂直分表

将表中字段较多的表按照字段拆分为多张表。

比如,把用户表拆分为基本信息和扩展信息两张表,减少了表的宽度提高了查询效率。

  • 水平分表

将同一张表的数据按照行拆分到多张表中。

比如,按照用户ID将用户表分为user_01和user_02等多张表,解决了单张表数据量过大导致的性能问题。

如何分库分表

  • 选择分片键(Shard Key)

分库分表需要选择一个合理的分片键,这会影响数据的分布和性能。

一般选择主键、时间戳,或者均匀分布数据的字段(常用UUID)作为分片键。

  • 路由策略

分库分表后,路由是需要知道访问的数据在哪个库或者表中。

  • 事务处理

分库分表后,事务中可能会出现跨库、跨表的情况。可以使用分布式事务、最终一致性等机制解决。

  • 数据迁移和扩容

数据迁移:在单库单表的基础上分库分表,需要进行数据迁移,可以编写脚本或者使用工具将数据迁移到新的分库分表架构中。

扩容:随着数据量的增长,需要考虑动态扩展数据库或者表的数量。

分库分表中间件

  • Mycat:分库分表中间件。
  • ShardingSphere:分库分表中间件,支持分布式事务。
  • TDDL:分布式数据库层,可以分库分表。

如果使用了Sequelize,还可以安装插件支持分库分表:

  • Sharding插件
  • 自定义ORM扩展:在ORM中自定义模型的数据库连接或查询方法,实现对不同数据库或表的访问。

性能监控和优化

分库分表架构建立后,需要持续监控新架构的系统性能以及根据监控调整分库分表策略。

Node.js分库分表简单实现

下面的实例将用户信息分散到了两个数据库中。

js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
const mysql = require('mysql2/promise');

// 两个数据库的配置信息
const dbConfigs = [
{ host: 'localhost', user: 'root', password: 'password', database: 'db1' },
{ host: 'localhost', user: 'root', password: 'password', database: 'db2' },
];

// 为每个数据库创建连接池
const pools = dbConfigs.map(config => mysql.createPool(config));

// 根据id将用户请求分散到多个数据库上,计算数据库偏移量
const getShard = (id) => id % dbConfigs.length;

const getUser = async (userId) => {
// 选择id为分片键
const shard = getShard(userId);
const pool = pools[shard];
const conn = await pool.getConnection();
const [rows] = await conn.query('SELECT * FROM users WHERE id = ?', [userId]);
conn.release();
return rows[0];
};

// 调用
getUser(1234456).then(user => console.log(user)).catch(err => console.error(err));

性能监控和调优

监控工具:PM2,New Relic,Datadog

服务器扩展

  • 垂直扩展

提升服务器硬件配置。

  • 水平扩展

增加服务器数量。

CDN

使用CDN缓存静态资源。

限流和降级

  • 限流

限制流量避免系统宕机。

  • 降级

系统压力较大时可以关闭部分非核心服务,有限保证核心服务。

评论