如何优化系统?

star2017 1年前 ⋅ 348 阅读

以下是我在10年开发过程中积累的一些经验,分享给大家。

循环调用数据库

for循环里面的调用mysql数据查询,如:订单列表中需要获取用户手机号,昵称,可能会在for循环里根据userId获取用户信息,这样就会频繁的调用查询接口,IO消耗会比较多。
伪代码如:

for(Order order : orders){
	User user = userService.getId(order.getUserId());
	....
}

优化后:

Map<Long,User> userMap = userService.getIds(userIds);
for(Order order : orders){
	User user = userMap.get(order.getUserId());
	....
}

访问数据库变成了一次。大大减少了IO请求。

数据库

索引

在开发的时候,需要考虑是否要加索引,表的数据是否会很多,如果数据量会比较多,那么需要提前考虑加上索引。不然可能会出现数据库不能运作的情况。

主键

innoDB主键不要太长,会导致空间占用过大;MYISAM就无所谓了;

缓冲池大小

尽量把缓冲池大小调大,可以通过innodb_buffer_pool_size参数来设置,因为缓冲池可以降低磁盘访问,提升性能,缓冲池常用算法是LRU。

写缓存

对于写多读少的场景,建议把写缓存调整的大一点,可以通过设置innodb_change_buffer_max_size参数来调整写缓存大小。但是对那种写了马上需要读的,或者读多写少的场景就不建议设置过大的写缓存。

数据丢失

数据库崩溃或者服务器奔溃导致数据丢失,需要检查下innodb_flush_log_at_trx_commit配置的值为多少?如果是0或者2那么会存在1秒的丢失,如果是1,那么数据不会丢失,但是影响性能。

id主键不易太长

如果数据库是innoDB时,数据库id主键不易太长,因为普通索引都会存储主键,所以会导致普通索引过于庞大;建议使用递增主键,否则可能会出现大量索引分裂,行记录移动的情况。

字符集

数据库编码建议选择utf8mb4,因为不能保证你的业务不会出现表情,特殊字符。

使用NOSQL

如果你的服务有很大的流量,那么不要用mysql扛大流量,尽量使用redis或者mongodb,毕竟nosql的性能要比mysql好的多。

大数据

如果系统中的表的数据量很大,那么此时需要考虑分库分表,水平切分可以提高吞吐量、数据量、读写量;也可以考虑使用一些大数据框架,如Hbase来存储数据,hive来处理数据和计算。

大数据统计

可以优化的思路:1、同一份数据尽量不要计算多次,可以考虑按一定的时间段进行切分,之后在进行合并就可以。2、可以分散处理的就不要集中处理,可以提高执行效率,3、可以减少单次计算的数据量。

表扩展性

通常的表扩展是通过列来进行扩展,如添加一个新字段,但是也可以通过行扩展,对于行扩展更加灵活,不需要添加字段,唯一的缺点就是多增加一行数据。

缓存优化

  1. 对于缓存如果一个id只是根据业务类型不同来区分,那么可以考虑通过value存储多个值来完成,如1_view=1000;1_live=200;1_comment=300;示例表示数据1的查看数是1000,点赞数是200,评论数是300,按这样的key设计,在返回数据1的时候需要查3次redis。可以调整为1=[1000,200,300],这样对redis的查询减少到了1次,减少了IO消耗。
  2. 读请求量很大的时候,可以加入缓存,这样不用每次都查数据库,也可以通过定时任务把需要的数据刷到缓存中,减少数据库的压力。

适当拆分

  1. 系统拆分需要谨慎,什么时候拆,怎么拆?过度拆分不一定会带来很大的收益,反而会对项目带来不必要的网络开销,前期量不大的情况下单应用完全没问题,可以提前按模块进行分层,方便后期的拆分。后期哪个业务量大就可以把该业务单独拆出来,形成微服务。
  2. 对流量强大的业务进行系统拆分,使其与业务系统解耦,如推送系统;
  3. 写入量巨大时,可以考虑把数据库进行水平拆分,如果写入量到达万级,百万级,可以使用mq来做缓冲,从而保护数据库不被打挂;

高并发

  1. 对于查询并修改高并发的问题:可以使用CAS来处理,因为使用分布式锁会降低吞吐量。如修改账户金额的时候,可以把老的金额作为修改条件来进行修改。
  2. 并行处理和批量处理可以提升性能,这是以空间换时间。
  3. 使用异步化来提升性能

选择合理的方案

  1. 有时候可以考虑使用长连接来代替短链接,可以提高性能,如需要对客户端做推送。
  2. 尽量不要把域名写死,可以使用配置,如app、h5获取域名都可以通过配置,因为有可能你的域名会不小心被封,也不要数据库里面把域名地址写死。
  3. 有些计算可以放前端的就放到前端去做,这样不会占用服务器的资源。

最终一致性方案

  1. 线下全量扫描;
  2. 线下增量扫描;
  3. 线上实时监测法;

秒杀系统

  1. 系统进行分层,每层都需要做缓存
  2. 尽量把请求拦截在上游,减少数据库的压力
  3. 读请求可以使用缓存,写请求使用队列进行限流
  4. 一定要做好压测
本文为博主原创文章,未经博主允许不得转载。
更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: