今天讲一下接口优化,接口优化是开发进阶避不开的一项任务,现在都讲究一个提升qps和吞吐量,应对高并发应用场景下的性能问题
接口优化可以从多个维度进行,常见策略:
代码层面
批处理:
数据库批量操作,比如批量修改语句,MyBatis-Plus 批处理其实是开启事务,批量语句是按 单条批量提交 的
/**
* 执行批量操作
*
* @param entityClass 实体类
* @param log 日志对象
* @param list 数据集合
* @param batchSize 批次大小
* @param consumer consumer
* @param <E> T
* @return 操作结果
* @since 3.4.0
*/
public static <E> boolean executeBatch(Class<?> entityClass, Log log, Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) {
Assert.isFalse(batchSize < 1, "batchSize must not be less than one");
return !CollectionUtils.isEmpty(list) && executeBatch(entityClass, log, sqlSession -> {
int size = list.size();
int idxLimit = Math.min(batchSize, size);
int i = 1;
for (E element : list) {
consumer.accept(sqlSession, element);
if (i == idxLimit) {
sqlSession.flushStatements();
idxLimit = Math.min(idxLimit + batchSize, size);
}
i++;
}
});
}
这样的批处理需要多次开启数据库连接,消耗性能,解决方案可以自己实现JDBC按照500条批量语句一次数据库连接,或者更改MyBatis-Plus批量操作实现,但批量操作在1000条以下时,性能差别并不明显,如果没有很慢的情况下,不建议去更改MyBatis-Plus批量操作
减少数据库查询:
禁止循环查询
避免不带查询条件全查
异步处理: 对于耗时的操作,如文件上传、邮件发送等,可以采用异步方式处理。
并行改串行:
数据传输优化:
压缩数据: 使用GZIP等压缩算法减少传输的数据量
分页和懒加载: 避免一次性加载大量数据。
缓存策略:
本地缓存: 使用Guava Cache。
分布式缓存: 如Redis、Memcached等,用于存储热点数据。热点缓存使用见文章: 一篇文章说清楚redis - 掘金 (juejin.cn)
CDN: 对于静态资源,使用CDN加速。
数据库优化:
索引优化: 确保查询语句有合适的索引。
- 删除冗余和重复索引
- 索引一般不能超过
5个 - 索引不适合建在有大量重复数据的字段上、如性别字段
- 适当使用覆盖索引
//增加索引
alter table user_info add index idx_name (name);
//查看执行计划
explain select * from user_info
//查看索引
show create table user_info;
SQL优化: 避免全表扫描,优化查询逻辑。
读写分离: 分离读写操作,减轻单个数据库的压力。
负载均衡:
使用负载均衡器如Nginx、HAProxy等,分散请求到多个服务器上。
性能监控与分析:
定期进行性能测试,使用工具如JMeter、LoadRunner等。
监控系统性能,如CPU、内存、磁盘IO等,及时发现瓶颈。
微服务架构:
如果适用,可以考虑将大应用拆分为多个微服务,提高系统的响应速度和可扩展性。
数据结构优化:
在Java中,可以考虑使用更高效的集合类,如ArrayList代替LinkedList在随机访问场景下。 减少不必要的对象创建,使用对象池等。如使用set替换hashMap,减少hash次数等
前端优化:
减少HTTP请求、图片优化、代码压缩
硬件升级:
升级服务器硬件
其他情况:
IO操作没关闭,线程打满了,大事务占用数据库连接等,具体问题具体分析