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分库分表简单实现
下面的实例将用户信息分散到了两个数据库中。
1 | const mysql = require('mysql2/promise'); |
性能监控和调优
监控工具:PM2,New Relic,Datadog
服务器扩展
- 垂直扩展
提升服务器硬件配置。
- 水平扩展
增加服务器数量。
CDN
使用CDN缓存静态资源。
限流和降级
- 限流
限制流量避免系统宕机。
- 降级
系统压力较大时可以关闭部分非核心服务,有限保证核心服务。