技术分享java架构设计专题优化专题

谈谈互联网的一些高并发设计手段

2019-09-19  本文已影响0人  先生zeng

途径

通过提高吞吐量降低响应延迟这两块方向来确保高并发。

性能优化的目标

  1. 缩短响应时间
  2. 提高并发数
  3. 让系统处于合理状态

优化手段

  1. 当时间是瓶颈的时候。

当系统的运行时间是主要的瓶颈而空间绰绰有余时,可以采用缓存复用计算结果,把计算的结果存入缓存,降低系统时间上的开销,因为缓存比较容易访问。

  1. 当空间比较缺少时

这时候就i可以考虑时间换空间了,当系统运行时间很快,而受限于空间的影响。举两个例子:

  1. 网络传输是瓶颈,这时候可以使用系统时间去使用http的gzip进行压缩,消费时间换取空间的

2.App的请求分类接口,可以使用版本号来判断哪些数据需要更新,只要下载需要更新的数据就可以了

  1. 找到系统的瓶颈的一些思路

  2. 分析系统业务流程,找到关键路径并分解优化。

  3. 比如,一个服务集群,一般前五的几个接口占用了百分之80的流量,这几个接口就是关键路径

  4. 对关键路径的代码优化收益一般是最大的,其他路径也要想办法进行优化。

整个优化手段上: 调用了多少rpc接口,载入多少数据,使用什么算法,非核心流程能否异步化,没有数据依赖的逻辑能否并行执行。

优化的层次

  1. 架构设计层次

    关注系统控制、数据流。

    如何拆分系统,使各部分系统整体负载更加均衡,降低系统内部开销。

  2. 算法逻辑层次

关注算法的选择是否高效,算法的逻辑进行优化,空间时间优化任务并行处理,使用无锁数据结构,避免加锁(CAS)。

空间换时间

ThradLocal

时间换空间

采用压缩算法压缩数据,更复杂的逻辑减少数据传输。

  1. 代码优化层次

关注代码细节优化,代码实现是否合理,是否创建过多的对象,循环遍历是否高效,cache使用是否合理,是否重用结算结果。

代码优化层次如下:

循环遍历是否高效:

不要在循环里调RPC接口、查询分布式缓存、执行SQL等,应该先调批量接口组装好数据,再循环处理。

代码需要注意避免生成过多对象或无效对象,比如输出log时候的log级别需要判断,避免new无效对象。

ArrayList、HashMap初始容量设置是否合理。

对数据对象是否合理重用,比如通过RPC查到的数据能复用则必须复用。

根据数据访问特性选择合适数据结构,比如读多写少,考虑 copyOnWrite。

拼接字符串的时候是使用String相加还是StringBuilder进行append(在StringBuilder的容量预分配的情况下,StringBuilder的性能比String相加性能提高15倍左右)。

是否正确初始化数据,有些全局共享的数据,饿汉式模式,在用户访问之前初始化。

数据库建表语句能尽量小的数据结构比如表示状态的字段,如果状态值在255以内使用unisigned tinyint,IP使用int而非varchar。

使用enum的场景使用tinyint,emum扩展需要该表。

避免使用select * 查询数据,只查询需要的字段,避免浪费数据IO、内存、CPU、网络传输。

分析查询场景建立合适的索引,分析字段的可选择性,索引长度,对长的varchar使用前缀索引

字段金量为not null类型,MySql手册说明允许null字段需要额外的存储空间处理null,并且很难查询优化

总结:

以上都是为了降低服务器CPU使用率、IO流量、内存占用、网络消耗、降低响应时间等等。

CPU Cache结构

速度越来越快: 内存 -> L3 -> L2 -> L1多级缓存

哪些数据适合缓存?

很聚焦的高频访问,时效性要求不高的适合缓存,比如很聚焦很高频访问业务数据如频道,栏目,广告位。
时效性要求不是很高的,更新了不用实时体现的适合缓存提高性能。

如果对数据时效性要求很高,需要考虑更新缓存带来的一致性问题。

时效性和缓存的冲突,比如商品服务对商品进行了缓存,由于缓存和更新商品不是同一个事务,则对数据时效性要求搞得如交易,就只能从数据库查询商品信息了。

image

算法逻辑优化层次如下:

image

架构设计优化逻辑

  1. 分布式系统微服务化
  2. 分库分表、读写分离、数据分片
  3. 无状态化设计、水平扩展
  4. 调用链路梳理、热点数据尽量靠近用户
  5. 分布式cache、多级多类型缓存
  6. 容量规划
  7. 提前拒绝,保证柔韧性可用。

案例分析

秒杀系统

开发场景分析:
架构设计方面

数据需要进行分层

image

数据分层次校验、上层尽量把无效请求过滤掉。

上层可以是不准确的过滤。

层层限流最后一层做数据一致性校验,扣减库存。

具体手段

  1. Html、js、css等静态资源文件缓存到用户端(APP或浏览器)

  2. 非实时动态数据(秒杀期间如商品标题、商品描述、图片URL列表、店铺信息、秒杀活动信息等),这些数据缓存在用户访问链路中靠近用户的位置、粗过滤一分部流量,比如用户是否有秒杀的资格、秒杀是否已结束等、这些数据实时性要求不高,这些数据放在第一层cache上面,这些数据在数据库发生变化时,通过MQ同步到cache。

  3. 实时数据如用户营销数据(红包、折扣、商品库存等)再过滤掉一批用户。这些数据放到第二层缓存里面,这些数据需要通过MQ进行同步。

  4. 经过多层过滤最终落到数据库的流量已经很少了,最终在数据库层面使用事务保证扣库存准确性。

image

feed系统

示例: 微信朋友圈

image

特性:

  1. 读多写少 100/1
  2. 冷热数据明显 80% 是当天数据,20%用户是活跃用户
  3. 热点效应明显 热点事件、重大节日、日常这些日期内,比较明显
  4. 高访问量

注意点

读多写少、冷热数据明显,热点数据缓存到调用链路更靠近用户的地方

L1缓存容量小,负责抗最热点的数据,L2缓存容量考虑目标是容量,缓存更大范围的数据,比如一般用户的timeLine,高热点数据单独缓存,比如设置白名单,大V的用户数据单独缓存。

数据分析各种timeline(关注的timeline、topic的timeline、一些运营的timeline)前几页的访问比例,像前三页占百分之97,把这种业务特性,把前几页的数据作为热点数据放进L1Cache。

image

push 或 pull

当用户发布数据是,是需要考虑把数据发送push给关注者(朋友),还是用户个人从关注的人中主动pull取消息。这就是push或pull。

比如微博,一个最火的明星有几千万关注者当发布一条消息时,考虑下,如何把消息传播出去。

实现

  1. 基于写扩散消息同一推送频道

  2. 推送策略: 拆分数据并行推,活跃用户先推,非活跃用户慢慢推。
    比如: 有1万个用户关注,发了一条消息,先拆分成100份,每份100个并行推
    1万个用户里,活跃的假设有2000个,则活跃用户先推送,非活跃用户慢慢推

    每个用户会维护一份活跃用户列表,用户上线,则为活跃用户。

  3. 消息标准化格式

  4. 统一数据流,职责明确


    image

数据存储选择

image
上一篇下一篇

猜你喜欢

热点阅读