接口性能优化的 15 个技巧
发布时间:2024-01-24 01:50

MySQL的底层 innodb ku体育app存储引擎采用 B+ 树结构,三层结构支持千万级的数据存储。

当然,现在互联网的用户基数非常大,这么大的用户量,单表通常很难支撑业务需求,将一个大表水平拆分成多张结构一样的物理表,可以极大缓解存储、访问压力。

分库分表也可能会带入很多问题:

每一个问题展开都要花费很长篇幅来讲解,这里主要讲接口性能优化的方案汇总,就不展开细讲了。

关于分库分表,市场受欢迎的开源框架是 sharding-jdbc,目前已经捐赠给Apache并启动孵化

虽然有了分库分表,从存储维度可以减少很大压力,但「富不过三代」,我们还是要学会精打细算,就比如所有的数据库操作都是通过 SQL 来执行。

一个不好的SQL会对接口性能产生很大影响。

比如:

SQL 优化的经验非常多,比如:

SQL 优化的内容非常多,这里就不展开了

有很多业务的计算逻辑比较复杂,比如页面要展示一个网站的 PV、微信的拼手气红包等

如果在用户访问接口的瞬间触发计算逻辑,而这些逻辑计算的耗时通常比较长,很难满足用户的实时性要求。

一般我们都是提前计算,然后将算好的数据预热到缓存中,接口访问时,只需要读缓存即可

是不是一下子就快了很多。

很多业务逻辑有事务要求,针对多个表的写操作要保证事务特性。

但事务本身又特别耗费性能,为了能尽快结束,不长时间占用数据库连接资源,我们一般要减少事务的范围。

将很多查询逻辑放到事务外部处理。

另外在事务内部,一般不要进行远程的 RPC 接口访问,一般占用的时间比较长。

如果数据量过大,除了采用关系型数据库的分库分表外,我们还可以采用 NoSQL

如:MongoDB、Hbase、Elasticsearch、TiDB

NoSQL 采用分区架构,对数据海量存储能较好的支持,但是事务方面可能没那么友好。

每一个 NoSQL 框架都有自己的特色,有支持 搜索的、有列式存储、有文档存储,大家可以根据自己的业务场景选择合适的框架。

当下的计算机CPU处理速度还是很多的,而 IO 一般是个瓶颈,如:磁盘IO、网络IO。

有这么一个场景,查询 100 个人的账户余额?

有两个设计方案:

方案一:开单次查询接口,调用方内部循环调用 100 次

方案二:服务提供方开一个批量查询接口,调用方只需查询 1 次

你觉得那种方案更好?

答案不言而喻,肯定是方案二

数据库的写操作也是一样道理,为了提高性能,我们一般都是采用批量更新。

并发业务,为了防止数据的并发更新对数据的正确性产生干扰,我们通常是采用 加锁 ,涉及独享资源每次只能是一个线程来处理。

问题点在于,锁是成对出现的,有加锁就是释放锁。

对于非竞争资源,我们没有必要圈在锁内部,会严重影响系统的并发能力。

控制锁的范围是我们要考虑的重点。

Tom哥带团队对小伙伴有要求,代码必须要有 code review 环节,review 同学代码经常发现一个问题。

当需要一个数据时,如果没有调 RPC 接口去查,比如想用户信息这种通用型接口

因为前面要用,肯定已经查过。但是我们知道方法的调用都是以栈帧的形式来传递,随着一个方法执行完毕而出栈,方法内部的局部变量也就被回收了。

后面如果又要用到这个信息,只能重新去查。

如果能定义一个Context 上下文对象,将一些中间信息存储并传递下来,会大大减轻后面流程的再次查询压力。

如何创建一个集合,这还不简单,很快我们就写出下面代码

List lists = Lists.newArrayList();

如果说,要往里面插入 1000000 个元素,有没有更好的方式?

我们做个试验:

场景一:

结果:1000000 次插入 List,花费时间:154

场景二:

结果:1000000 次插入 List,花费时间:134

如果我们预先知道集合要存储多少元素,初始化集合时尽量指定大小,尤其是容量较大的集合。

ArrayList 初始大小是 10,超过阈值会按 1.5 倍大小扩容,涉及老集合到新集合的数据拷贝,浪费性能。

避免一次从 DB 中查询大量的数据到内存中,可能会导致内存不足,建议采用分批、分页查询

服务热线
在线咨询