精华内容
下载资源
问答
  • 一、缓存 浏览器与服务器之间通过http header传递缓存信息,通过设置http header配置缓存机制。 cache-control cache-control可以在http request header中存在 也可以在http response header中存在 其作用就是让...

    一、缓存
    浏览器与服务器之间通过http header传递缓存信息,通过设置http header配置缓存机制。

    cache-control

    1. cache-control可以在http request header中存在
    2. 也可以在http response header中存在
    3. 其作用就是让浏览器与服务器相互知道各自那边的缓存策略情况。

    cache-control的属性

    1. max-age:指定缓存的最大有效时间。在这段时间之内有效,浏览器不用再向服务器请求,直接从缓存中读。status:200(from memory cache)。expires是过期时间配置(http1.0),优先级没有max-age高。
    2. s-maxage:如果既设置了max-age又设置了s-maxage。返回状态是304(去CDN拿的)。s-maxage只能指定public的缓存时间,比如CDN、代理服务器。
      private缓存设备:只适用于当前用户访问并且读取信息。
      public缓存设备:能被很多用户访问并且读取信息的。
      s-maxage优先级高于max-age.
      s-maxage对于public缓存设备来说才是有效的。
      所以,s-maxage是对于CDN这样公共的public缓存设备来说的资源过期时间,浏览器从CDN取得资源,返回状态码304。
    3. no-cache:不会直接去浏览器缓存中读,会发请求到服务器,通过服务器的一些信息(比如:last-modified)来判断浏览器端的缓存是否过期,从而知道缓存策略。
    4. no-store:对资源不使用任何缓存策略。

    Expires

    Expire:缓存过期时间,用来指定资源的到期时间,是服务器端的具体时间点,告诉浏览器在过期时间前,浏览器可以直接从浏览器缓存取数据,而无需再次请求。

    max-age也是这个意思,但max-age优先级高于expires,当没有设置max-age时,expires就生效。

    expires和max-age都是浏览器端的缓存策略,在过期时间之前,都直接从浏览器缓存中读取数据。

    但当服务器文件资源发生变化后,浏览器端并不会更新资源,这就引出了Last-Modified和If-Modified-Since这两字段。

    Last-Modified、If-Modified-Since

    • 基于客户端和服务端协商的缓存机制,可以取得最新的资源
    • Last-Modified——response header
    • If-Modified-Since——request header
    • 需与cache-control共同使用

    返回304,服务端资源没更新,客户端直接从缓存中读取资源。
    返回200,服务端资源更新了,并发给客户端一份更新过的文件。

    也就是说,当cache-control配了max-age,且max-age没有过期,会优先走max-age,从浏览器中读相关的文件,当max-age过期后,浏览器和服务器才会通过Last-Modified / If-Modified-Since进行协商,由服务端控制合理的缓存方式。

    但Last-Modified有缺点。

    Last-Modified的缺点

    1. 某些服务端不能获取精确的修改时间,也就不能准确返回。
    2. 文件修改时间改了,但文件内容却没有变

    Etag的出现解决了该问题。

    Etag / If-None-Match

    1. 文件内容的hash值,能唯一标识文件,当文件内容改变,hash值会跟着变化。
    2. Etag——response header
    3. If-None-Match——request header
    4. 需要与cache-control共同使用

    实际上就是——分级缓存策略

    通过对服务端的配置实现缓存策略。
    在这里插入图片描述
    二、缓存流程图
    在这里插入图片描述
    在这里插入图片描述

    二、服务端性能优化

    Vue渲染面临的问题是什么?为什么要用vue-ssr
    在这里插入图片描述
    多层次的优化方案

    1. 构建层模板编译
      在webpack构建的时候将模板语法template编译成浏览器可以直接执行的html代码。
    2. 数据无关的prerender的方式
      将每个用户看起来都一样的页面在webpack构建层直接编译成html代码,用户直接访问html,这样在浏览器端不会执行vue相关的代码。
    3. 服务端渲染
      将浏览器端要做的运算移到服务端,是运算能力的平衡。
      在服务端获取数据渲染页面,返回给浏览器html,能直接渲染出页面。
      (vue-ssr:将首屏相关的一些数据在服务端直接生成html返回给客户端,客户端将html渲染出来,而不是在客户端执行相应的JS从而渲染出页面。所以,vue-ssr解决首屏渲染的问题)
    展开全文
  • 服务端 缓存使用总结

    千次阅读 2016-09-12 18:28:53
    服务端缓存使用总结缓存类型 localcache memcache redis 区别对比 缓存类型 使用场景 使用示例 优点 缺点 localcache 少量数据,对应用程序只读或读多写少 后台配置,分区信息 无需网络开心,访问速度最快 ...

    服务端缓存使用总结

    缓存类型

    1. localcache
    2. memcache
    3. redis

    区别对比

    缓存类型 使用场景 使用示例 优点 缺点
    localcache 少量数据,对应用程序只读或读多写少 后台配置,分区信息 无需网络开心,访问速度最快 集群机器数据不同步
    memcache 海量数据,高并发读写 评论内容,账号信息 内存占用相对redis少,适合大键存储 数据结构单一,不支持备份及持久化,只支持客户端操作
    redis 海量数据,高并发读写 评论id索引,收藏视频信息 数据结构丰富,支持备份及持久化,支持服务器操作 相对memcache内存效率低

    - localcache适用于存储少量数据及对应用程序只读或读多写少的场景,例如后台黑白名单、推广信息等,因为应用程序对这些数据几乎只是只读的,数据的修改主要发生在后台管理员更新配置时,且这些数据量很少,完全可以存储在本地内存当中。应用程序只需要定期从数据库load数据进行更新即可。对于分布式集群的部署,每台机器独自维护一份localcache,单后台数据有变动时,不同机器不可能同时load更新,因此存在集群机器数据不一致的情况。 但是这种情况通常是在可接受范围内的。
    - memcache适用于存储大量高并发读写的数据,减轻数据库访问压力。如果没有memcache缓存,所有的访问直接打到db,高并发情况下将立马把数据库打挂,由于是直接存储在内存当中,因此访问速度将大大降低,同时数据缓存在memcache集群当中,可以确保应用集群访问数据的一致性,而不会存在localcache当中的问题。由于memcache不支持持久化,一旦集群机器出现宕机,将导致所有数据丢失,但是memcache本身就不是为了持久化数据而存在的,所以这也不是一个问题,需要注意的是,一旦memcache出现宕机等情况需要服务重启时,需要对缓存进行预热,不然大量miss同样也会打挂数据库。
    - redis同样也是为了应对高并发读写而存在的。和memcache一样也是k-v类型,但是redis支持更丰富的数据结构,list,set,sortset,hashes。由于redis数据不是完全存在内存当中,当redis内存耗尽时,长期不使用的value将被转移到磁盘,因此redis可以存储比自身内存大的数据。同时redis支持持久化及master-slave模式数据备份。重启时可以再次加载磁盘的数据到内存当中。redis还具有容灾模式,只需要开启aof,即使服务器宕机也可以通过aof文件进行数据恢复。是否使用持久化及开启aof要根据具体业务场景进行选择。

    缓存更新逻辑

    cache then db or db then cache?

    • 对于cache和db的操作顺序,网上一直存在不同的观点,到底是先更新数据库再淘汰缓存,还是先淘汰缓存再更新数据库呢。我们的做法是先更新数据库在淘汰缓存。
    • 首先先分析一下两者可能导致的最差情况(不考虑db和cache其中一个操作失败的情况)。

      1. 先淘汰缓存在更新数据库。对于这种做法,如果淘汰了缓存,此时刚好来了一个请求,由于缓存已经被淘汰,新来的请求将从数据库读取信息重新load到缓存,如果先前的写操作还没完成,读操作读到的将是旧的数据,此时重新load到缓存的数据将是脏数据并且后续的请求将都读到脏数据。
      2. 先更新了db,后续cache操作失败,此时将会导致cache中的数据是脏数据。

    在考虑了更新失败的情况下,分布式服务中并没有完美的解决方案,方法需要自己根据业务进行权衡,除非你愿意牺牲性能使用事务强一致性

    update cache or delete cache ?

    • 写操作发生时,是更新缓存还是删除缓存呢。facebook在 Scaling Memcache at Facebook中使用的策略是更新数据库后删除memcache缓存。为什么是删除缓存而不是更新缓存呢?假设并发写更新完数据库后同时去更新缓存。此时两个写操作可能都从缓存中取到了数据A,此时将导致并发写导致脏数据。
    • 并发写操作导致脏数据的情况是因为必须先从memcache中取出数据修改完在写回。但是在redis中,由于redis支持服务器操作,INCE,HINCR等操作都可以直接在服务器当中操作完成,对于这类操作不存在并发写的问题,因此可以选择更新db后更新缓存。直接update将减少一次cache miss。
    • 在我们的大多数业务场景中,我们使用的是更新db后更新缓存。虽然更新缓存可能导致并发写脏数据。但是由于我们使用了kafka消息队列,并发写操作经过kafka后是可以转化为顺序写的。比如对于评论。同一个视频下面可能有多条并发写评论,视频收到评论后需要更新视频的评论数信息,如果直接更新缓存有很大的几率导致并发写脏数据,但是我们使用视频aid作为key,通过kafka消息队列异步处理,这样对于同一个视频的写操作都会发送到同一个kafka分区,同时对于consumer来说,同一个视频的写操作都会由同一个consumer消费,通过消息队列异步化处理,即可把并发写转化为顺序写,此时更新缓存就不会存在写竞争。
    • 到底delete还是update,还是得自己根据业务场景进行权衡。

    redis使用

    • 业务中,redis的使用占绝大部分,且相对于memcache,由于丰富的数据结构,redis的使用也相对比较复杂。因此着重讲讲redis使用的一些注意事项
      redis数据类型选择

    Use hashes when possible

    • redis的内存效率是比较低的,尤其是使用k-v的时候,在http://redis.io/topics/memory-optimization这这篇博客中明确说明。能使用hashes的地方尽量使用hashes,在使用k-v结构的时候,每一个value都是一个redisObject,当使用hashes的时候,redis使用的压缩列表和字典两种存储方式,使用压缩列表的时候,由于压缩列表内存的优化,将大大节省内存空间。 redisObject typedef struct redisObject { unsigned type:4; unsigned encoding:4; unsigned lru:LRU_BITS; int refcount; void *ptr; } robj;
    • 例如视频下评论信息,可以使用 aid-rpid =》 replyinfo,即aid-rpid作为key,replyinfo作为value,也可以使用aid =》rpid-replyifo,即aid作为key,value是hashes,hashes的key是rpid,value是replyinfo。经过测试,在同样100W个key的情况下使用后一种方法可以比第一种节约大量的内存。同时,第二种方法还可以通过HGET aid 获取指定评论,也可以HGETALL aid获取所有评论。第一种则只能先 KEYS aid*获取rpid在去查询info。

    sortset

    • sortset的实现采用了跳表和字典两种数据结构,跳表保证rank及范围查询时O(logN)的复杂度,字典则使得score查询时能达到O(1)的时间复杂度. 使用sortset时需要注意的一点是sortset的大小,由于sortset是插入排序,如果sortset里数据量太大,可能导致插入排序速度太慢。

    set

    • set底层使用的其实是dict,其实就是一个value为null的hashes。需要注意的是,在某些场景下,可以使用二进制数组来替代set节省内存空间,通过GETBIT,SETBIT设置member判断member是否存在。
      redis底层图解

    redis expire

    • 不同于memcache必须在set key的时候指定expire time,redis可以在set的时候指定expiretime,也可以在使用途中在设置expiretime。
    • 那么何时设置expire呢,是在set数据前之前还是set数据之后呢。在业务中曾经犯过这样一个错误。用户查询收藏夹信息的时候会先查询缓存,如果缓存miss则从db中加载。收藏夹信息在redis中是以sortset方式存储的。score表示收藏时间。当用户添加收藏的时候,就把新的数据ZADD进去,然后expire 增加过期时间。粗看是没什么问题,但是这个时候忽略了一个问题,就是zadd前缓存过期了,下次查询的时候由于zadd数据存在将不会miss导致读到的只是最新zadd的数据!
    • 因此在执行类似zadd sadd hset等操作的时候,一定要先进行expire,如果miss则不执行,等到查询miss的时候在从db中load 。

    hashes 拆分

    • 是否有必要对hashes进行拆分?答案是肯定的。原因如下
      减小hashes粒度,增加查询效率。
      分散存储空间,redis当中,hashes的k-v只会保存在一个节点,如果所有的数据全部存在一个hashes,将导致节点数据不均衡。相反,把hashes进行拆分,每个hashes保存的只是部分数据,不同的hashes也会被分配到集群的不同节点。均衡集群的内存负载。
    展开全文
  • #服务端缓存使用总结

    2016-11-04 13:34:02
    服务端缓存使用总结缓存类型 localcache memcache redis 区别对比 缓存类型 使用场景 使用示例 优点 缺点 localcache 少量数据,对应用程序只读或读多写少 后台配置,分区信息 无需网络开心,访问速度最快 ...

    服务端缓存使用总结

    缓存类型

    1. localcache
    2. memcache
    3. redis

    区别对比

    缓存类型 使用场景 使用示例 优点 缺点
    localcache 少量数据,对应用程序只读或读多写少 后台配置,分区信息 无需网络开心,访问速度最快 集群机器数据不同步
    memcache 海量数据,高并发读写 评论内容,账号信息 内存占用相对redis少,适合大键存储 数据结构单一,不支持备份及持久化,只支持客户端操作
    redis 海量数据,高并发读写 评论id索引,收藏视频信息 数据结构丰富,支持备份及持久化,支持服务器操作 相对memcache内存效率低

    - localcache适用于存储少量数据及对应用程序只读或读多写少的场景,例如后台黑白名单、推广信息等,因为应用程序对这些数据几乎只是只读的,数据的修改主要发生在后台管理员更新配置时,且这些数据量很少,完全可以存储在本地内存当中。应用程序只需要定期从数据库load数据进行更新即可。对于分布式集群的部署,每台机器独自维护一份localcache,单后台数据有变动时,不同机器不可能同时load更新,因此存在集群机器数据不一致的情况。 但是这种情况通常是在可接受范围内的。
    - memcache适用于存储大量高并发读写的数据,减轻数据库访问压力。如果没有memcache缓存,所有的访问直接打到db,高并发情况下将立马把数据库打挂,由于是直接存储在内存当中,因此访问速度将大大降低,同时数据缓存在memcache集群当中,可以确保应用集群访问数据的一致性,而不会存在localcache当中的问题。由于memcache不支持持久化,一旦集群机器出现宕机,将导致所有数据丢失,但是memcache本身就不是为了持久化数据而存在的,所以这也不是一个问题,需要注意的是,一旦memcache出现宕机等情况需要服务重启时,需要对缓存进行预热,不然大量miss同样也会打挂数据库。
    - redis同样也是为了应对高并发读写而存在的。和memcache一样也是k-v类型,但是redis支持更丰富的数据结构,list,set,sortset,hashes。由于redis数据不是完全存在内存当中,当redis内存耗尽时,长期不使用的value将被转移到磁盘,因此redis可以存储比自身内存大的数据。同时redis支持持久化及master-slave模式数据备份。重启时可以再次加载磁盘的数据到内存当中。redis还具有容灾模式,只需要开启aof,即使服务器宕机也可以通过aof文件进行数据恢复。是否使用持久化及开启aof要根据具体业务场景进行选择。

    缓存更新逻辑

    cache then db or db then cache?

    • 对于cache和db的操作顺序,网上一直存在不同的观点,到底是先更新数据库再淘汰缓存,还是先淘汰缓存再更新数据库呢。我们的做法是先更新数据库在淘汰缓存。
    • 首先先分析一下两者可能导致的最差情况(不考虑db和cache其中一个操作失败的情况)。

      1. 先淘汰缓存在更新数据库。对于这种做法,如果淘汰了缓存,此时刚好来了一个请求,由于缓存已经被淘汰,新来的请求将从数据库读取信息重新load到缓存,如果先前的写操作还没完成,读操作读到的将是旧的数据,此时重新load到缓存的数据将是脏数据并且后续的请求将都读到脏数据。
      2. 先更新了db,后续cache操作失败,此时将会导致cache中的数据是脏数据。

    在考虑了更新失败的情况下,分布式服务中并没有完美的解决方案,方法需要自己根据业务进行权衡,除非你愿意牺牲性能使用事务强一致性

    update cache or delete cache ?

    • 写操作发生时,是更新缓存还是删除缓存呢。facebook在 Scaling Memcache at Facebook中使用的策略是更新数据库后删除memcache缓存。为什么是删除缓存而不是更新缓存呢?假设并发写更新完数据库后同时去更新缓存。此时两个写操作可能都从缓存中取到了数据A,此时将导致并发写导致脏数据。
    • 并发写操作导致脏数据的情况是因为必须先从memcache中取出数据修改完在写回。但是在redis中,由于redis支持服务器操作,INCE,HINCR等操作都可以直接在服务器当中操作完成,对于这类操作不存在并发写的问题,因此可以选择更新db后更新缓存。直接update将减少一次cache miss。
    • 在我们的大多数业务场景中,我们使用的是更新db后更新缓存。虽然更新缓存可能导致并发写脏数据。但是由于我们使用了kafka消息队列,并发写操作经过kafka后是可以转化为顺序写的。比如对于评论。同一个视频下面可能有多条并发写评论,视频收到评论后需要更新视频的评论数信息,如果直接更新缓存有很大的几率导致并发写脏数据,但是我们使用视频aid作为key,通过kafka消息队列异步处理,这样对于同一个视频的写操作都会发送到同一个kafka分区,同时对于consumer来说,同一个视频的写操作都会由同一个consumer消费,通过消息队列异步化处理,即可把并发写转化为顺序写,此时更新缓存就不会存在写竞争。
    • 到底delete还是update,还是得自己根据业务场景进行权衡。

    redis使用

    • 业务中,redis的使用占绝大部分,且相对于memcache,由于丰富的数据结构,redis的使用也相对比较复杂。因此着重讲讲redis使用的一些注意事项
      redis数据类型选择

    Use hashes when possible

    • redis的内存效率是比较低的,尤其是使用k-v的时候,在http://redis.io/topics/memory-optimization这这篇博客中明确说明。能使用hashes的地方尽量使用hashes,在使用k-v结构的时候,每一个value都是一个redisObject,当使用hashes的时候,redis使用的压缩列表和字典两种存储方式,使用压缩列表的时候,由于压缩列表内存的优化,将大大节省内存空间。 redisObject typedef struct redisObject { unsigned type:4; unsigned encoding:4; unsigned lru:LRU_BITS; int refcount; void *ptr; } robj;
    • 例如视频下评论信息,可以使用 aid-rpid =》 replyinfo,即aid-rpid作为key,replyinfo作为value,也可以使用aid =》rpid-replyifo,即aid作为key,value是hashes,hashes的key是rpid,value是replyinfo。经过测试,在同样100W个key的情况下使用后一种方法可以比第一种节约大量的内存。同时,第二种方法还可以通过HGET aid 获取指定评论,也可以HGETALL aid获取所有评论。第一种则只能先 KEYS aid*获取rpid在去查询info。

    sortset

    • sortset的实现采用了跳表和字典两种数据结构,跳表保证rank及范围查询时O(logN)的复杂度,字典则使得score查询时能达到O(1)的时间复杂度. 使用sortset时需要注意的一点是sortset的大小,由于sortset是插入排序,如果sortset里数据量太大,可能导致插入排序速度太慢。

    set

    • set底层使用的其实是dict,其实就是一个value为null的hashes。需要注意的是,在某些场景下,可以使用二进制数组来替代set节省内存空间,通过GETBIT,SETBIT设置member判断member是否存在。
      redis底层图解

    redis expire

    • 不同于memcache必须在set key的时候指定expire time,redis可以在set的时候指定expiretime,也可以在使用途中在设置expiretime。
    • 那么何时设置expire呢,是在set数据前之前还是set数据之后呢。在业务中曾经犯过这样一个错误。用户查询收藏夹信息的时候会先查询缓存,如果缓存miss则从db中加载。收藏夹信息在redis中是以sortset方式存储的。score表示收藏时间。当用户添加收藏的时候,就把新的数据ZADD进去,然后expire 增加过期时间。粗看是没什么问题,但是这个时候忽略了一个问题,就是zadd前缓存过期了,下次查询的时候由于zadd数据存在将不会miss导致读到的只是最新zadd的数据!
    • 因此在执行类似zadd sadd hset等操作的时候,一定要先进行expire,如果miss则不执行,等到查询miss的时候在从db中load 。

    hashes 拆分

    • 是否有必要对hashes进行拆分?答案是肯定的。原因如下
      减小hashes粒度,增加查询效率。
      分散存储空间,redis当中,hashes的k-v只会保存在一个节点,如果所有的数据全部存在一个hashes,将导致节点数据不均衡。相反,把hashes进行拆分,每个hashes保存的只是部分数据,不同的hashes也会被分配到集群的不同节点。均衡集群的内存负载。
    展开全文
  • Java服务端性能优化的常见方案

    千次阅读 2018-05-05 11:35:23
    作为一个Java后端开发,我们写出的大部分代码都决定...《Java程序性能优化》说性能优化包含五个层次:设计调优、代码调优、JVM调优、数据库调优、操作系统调优等。而每一个层次又包含很多方法论和最佳实践。本文只举...

    作为一个Java后端开发,我们写出的大部分代码都决定着用户的使用体验。如果我们的后端代码性能不好,那么用户在访问我们的网站时就要浪费一些时间等待服务器的响应,造成极差的用户体验,这就可能导致用户投诉甚至用户的流失。

    性能优化是一个很大的话题。《Java程序性能优化》说性能优化包含五个层次:设计调优、代码调优、JVM调优、数据库调优、操作系统调优等。而每一个层次又包含很多方法论和最佳实践。本文只举几个常用的Java代码优化方案,可以真正应用到项目中的方案。

    1、使用单例

    对于IO处理、数据库连接、配置文件解析加载等一些非常耗费系统资源的操作,我们必须对这些实例的创建进行限制,或者是始终使用一个公用的实例,以节约系统开销,这种情况下就需要用到单例模式。

    2、使用Future模式
    假设一个任务执行起来需要花费一些时间,为了省去不必要的等待时间,可以先获取一个“提货单”,即Future,然后继续处理别的任务,直到“货物”到达,即任务执行完得到结果,此时便可以用“提货单”进行提货,即通过Future对象得到返回值。

    public class RealData implements Callable<String> {  
        protected String data;  
    
        public RealData(String data) {  
            this.data = data;  
        }  
    
        @Override  
        public String call() throws Exception {  
            //利用sleep方法来表示真是业务是非常缓慢的  
            try {  
                Thread.sleep(1000);  
            } catch (InterruptedException e) {  
                e.printStackTrace();  
            }  
            return data;  
        }  
    }  
    
    public class Application {  
        public static void main(String[] args) throws Exception {  
            FutureTask<String> futureTask =   
                    new FutureTask<String>(new RealData("name"));  
            ExecutorService executor =   
                    Executors.newFixedThreadPool(1); //使用线程池  
            //执行FutureTask,相当于上例中的client.request("name")发送请求  
            executor.submit(futureTask);  
            //这里可以用一个sleep代替对其他业务逻辑的处理  
            //在处理这些业务逻辑过程中,RealData也正在创建,从而充分了利用等待时间  
            Thread.sleep(2000);  
            //使用真实数据  
            //如果call()没有执行完成依然会等待  
            System.out.println("数据=" + futureTask.get());  
        }  
    }

    3、使用线程池

    合理利用线程池能够带来三个好处。第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。
    在 Java 5 之后,并发编程引入了一堆新的启动、调度和管理线程的API。Executor 框架便是 Java 5 中引入的,其内部使用了线程池机制,它在 java.util.cocurrent 包下,通过该框架来控制线程的启动、执行和关闭,可以简化并发编程的操作。

    public class MultiThreadTest {
        public static void main(String[] args) {
            ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("thread-%d").build();
            ExecutorService executor = new ThreadPoolExecutor(2, 5, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory);
            executor.execute(new Runnable() {
                @Override
                public void run() {
                   System.out.println("hello world !");
                }
            });
            System.out.println(" ===> main Thread! " );
        }
    }

    4、使用NIO

    JDK自1.4起开始提供全新的I/O编程类库,简称NIO,其不但引入了全新高效的Buffer和Channel,同时,还引入了基于Selector的非阻塞 I/O机制,将多个异步的I/O操作集中到一个或几个线程当中进行处理,使用NIO代替阻塞I/O能提高程序的并发吞吐能力,降低系统的开销。
    对于每一个请求,如果单独开一个线程进行相应的逻辑处理,当客户端的数据传递并不是一直进行,而是断断续续的,则相应的线程需要 I/O等待,并进行上下文切换。而使用NIO引入的Selector机制后,可以提升程序的并发效率,改善这一状况。

    public class NioTest {  
        static public void main( String args[] ) throws Exception {  
            FileInputStream fin = new FileInputStream("c:\\test.txt");  
            // 获取通道  
            FileChannel fc = fin.getChannel();  
            // 创建缓冲区  
            ByteBuffer buffer = ByteBuffer.allocate(1024);  
            // 读取数据到缓冲区  
            fc.read(buffer);  
            buffer.flip();  
            while (buffer.remaining()>0) {  
                byte b = buffer.get();  
                System.out.print(((char)b));  
            }  
            fin.close();  
        }  
    }  

    5、锁优化

    在并发场景中,我们的代码中经常会用到锁。存在锁,就必然存在锁的竞争,存在锁的竞争,就会消耗很多资源。那么,如何优化我们Java代码中的锁呢?主要可以从以下几个方面考虑:

    • 减少锁持有时间
      可以使用同步代码块来代替同步方法。这样可以减少锁持有的时间。
    • 减少锁粒度
      要在并发场景中使用Map的时候,记得使用ConcurrentHashMap来代替HashTable和HashMap。
    • 锁分离
      普通锁(如syncronized)会导致读阻塞写、写也会阻塞读,同时读读与写写之间也会进行阻塞,可以想办法将读操作和写操作分离开。
    • 锁粗化
      有些情况下我们希望把很多次锁的请求合并成一个请求,以降低短时间内大量锁请求、同步、释放带来的性能损耗。
    • 锁消除
      锁消除是Java虚拟机在JIT编译是,通过对运行上下文的扫描,去除不可能存在共享资源竞争的锁,通过锁消除,可以节省毫无意义的请求锁时间。

    6、压缩传输

    在进行数据传输之前,可以先将数据进行压缩,以减少网络传输的字节数,提升数据传输的速度,接收端可以将数据进行解压,以还原出传递的数据,并且,经过压缩的数据还可以节约所耗费的存储介质(磁盘或内存)的空间以及网络带宽,降低成本。当然,压缩也并不是没有开销的,数据压缩需要大量的CPU计算,并且,根据压缩算法的不同,计算的复杂度以及数据的压缩比也存在较大差异。一般情况下,需要根据不同的业务场景,选择不同的压缩算法。

    7、缓存结果

    对于相同的用户请求,如果每次都重复的查询数据库,重复的进行计算,将浪费很多的时间和资源。将计算后的结果缓存到本地内存,或者是通过分布式缓存来进行结果的缓存,可以节约宝贵的CPU计算资源,减少重复的数据库查询或者是磁盘I/O,将原本磁头的物理转动变成内存的电子运动,提高响应速度,并且线程的迅速释放也使得应用的吞吐能力得到提升。

    以上内容参考自作者Hollis的人人都能掌握的Java服务端性能优化方案

    展开全文
  • 在程序设计中,缓存是典型的用空间换时间来获得程序性能提升的手段。...下图是关于服务端缓存设计的核心技术点。 何时需要缓存? 《高并发架构设计》一文指出当QPS大于50,将达到单机DB性能的极...
  • 这篇文章,我会尝试编写一个非常简单、小巧的中间件,完成服务端缓存功能,进而优化性能。 关于中间件 说到中间件,Express 官网对它的阐述是这样的: “Express 是一个自身功能极简,完全是路由
  • 缓存使用及优化方案

    千次阅读 2018-04-24 01:55:00
    缓存使用及优化方案 关于缓存 在计算机技术里,大家对于缓存一词肯定不陌生,CPU有缓存、数据库有缓存、静态资源缓存CDN、Redis等等; 在这里我们谈的主要是服务器缓存技术,服务端性能优化,最常用的手段就是...
  • 文章目录Pre概影响性能的因素响应时间 与 QPS线程数 与 QPS如何发现瓶颈工具 JProfiler 和 Yourkit如何简单的判断 CPU 是不是瓶颈如何优化系统减少编码减少序列化Java 极致优化并发读优化总结 Pre 小工匠聊架构-...
  • 对于常规项目,服务端的压力通常来自以下几个方面: 数据处理 1.1 接收请求 1.2 处理请求(响应时间) 数据存储 2.1物理介质存储容量上限 2.2大量数据的存储,影响数据处理速度 物联网项目特点 ...
  • webpack 缓存问题处理解决方案 导读 在该篇博文中,我们将逐步实现文件hash后缀的输出,修改某个文件,才会对应输出修改该文件的hash后缀,同时满足性能优化,客服端服务端代码同步更新 项目地址:...
  • 页面数据接口,返回数据很大,此Ajax请求在页面所有请求中是最耗时的,虽然服务端对接口做了缓存,但还是觉得返回数据很大,可以试着优化下接口数据结构。 前端通过JS模板引擎生成html,这需要消耗点资源,而且这种...
  • 自动化缓存策略-处理大规模缓存方案 http-Header(协议头部):基于http-Request(请求头部)和http-Response(响应头)来实现的缓存策略 缓存策略(一)cache-control 属性: max-age:指定缓存的有效时间 s-max...
  • 关于前端缓存优化

    千次阅读 2019-07-04 16:59:08
    关于缓存,大概可以分为以下几种: ① CDN缓存 ② DNS缓存 ③ 客户端缓存(无需请求的memory cache,disk cache;需要发请求验证的Etag/Last-Modified304) ④ Service Worker与缓存及离线缓存 ⑤ PageCache与...
  • 304 Not Modified: 协商缓存,浏览器在本地没有命中的情况下请求头中发送一定的校验数据到服务端,如果服务端数据没有改变,浏览器从本地缓存响应,返回 304。 快速,发送的数据很少,支付你会一些基本的...
  • 一种缓存优化方案响应头'Last-Modified'和请求头'If-Modified-Since''Keep-Alive'响应头和不离线的URLSession'Expires'响应头这篇文章的意义 正文开始 首先要说一件重要的事: NSCache和NSURLCa
  • ffmpeg推拉流优化方案

    千次阅读 2020-04-20 17:02:46
    文章目录ffmpeg推拉流优化方案一、卡顿优化设备老旧视频流音视频不同步网络二、延时优化三、传输协议优化四、首屏秒开优化服务器做优化客户端优化五、弱网优化六、DNS劫持优化七、服务端cdn优化 主要从以下几点来...
  • Android开发——WebView轻量缓存优化

    千次阅读 2017-11-28 12:56:20
    建议优化流量的消耗,可以对加载画质进行选择。想比淘宝 APP,消耗流量可是大多了。[2017-06-01 21:43:36] 怎么没用有流量节约模式,一会用了我 200M。[2017-06-12 08:32:25] 严选 app 太费流量了。于是乎
  • 达达-高性能服务端优化之路

    千次阅读 2015-11-05 10:56:10
    而数据库显然无法通过简单的添加机器来实现扩展,因此我们采取了Mysql主从同步和应用服务端读写分离的方案。 Mysql支持主从同步,实时将主库的数据增量复制到从库,而且一个主库可以连接多个从库同步...
  • 秒杀系统优化方案

    2020-02-16 00:22:20
    秒杀接口的简单流程 ...2.用户是否有收货地址 3.库存是否充足,没有库存返回失败 ...1.页面缓存+ URL缓存+对象缓存 2.页面静态化,前后端分离 3.静态资源优化 4.CDN优化 页面缓存 如前端页面使用的是Thy...
  • 前端 api 请求缓存方案

    千次阅读 2019-04-27 10:45:56
    在开发 web 应用程序时,性能都是必不可少的话题。对于webpack打包的单页面应用程序而言,我们可以采用很多方式来对性能进行优化,比方说 tree-shaking...而事实上,缓存一定是提升web应用程序有效方法之一,尤其是...
  • 常见的Android优化方案

    千次阅读 2016-03-03 20:03:00
    收集整理了平时工作中常见的需要注意的优化方案,文章只是以提纲的方式列出,没有做深入分析,其目的只是起到一个提醒的作用,在脑中有这个概念即可,工作中能有想到,然后能以keyword的方式搜索到就够了。...
  • H5性能优化方案

    千次阅读 2016-08-17 18:06:07
    H5性能优化意义对于一个H5的产品,功能无疑很重要,但是性能同样是用户体验中不可或缺的一环。原本H5的渲染性能就不及native的app,如果不把性能优化做起来,将极大地影响用户使用产品的积极性。用户感受当用户能够...
  • Redis 性能调优——缓存设计优化

    千次阅读 2019-07-31 19:51:18
    Redis 是一个开源的高性能的 Key-Value 服务器。本篇主要介绍一下缓存的设计与优化
  • 从输入url,到页面的画面展示的过程 一、白屏时间 二、白屏时间的重要性 三、白屏的过程 四、白屏-性能优化 1. DNS解析优化 2. TCP网络链路优化 3. 服务端处理优化 4. 浏览器下载、解析、渲染页面优化 内联关键CSS
  • 前端项目优化 -Web 开发常用优化方案、Vue & React 项目优化
  • 首屏渲染快(可在服务端缓存页面,请求到来直接给 html) 缺点: 代码改动大、需要做特定SSR框架的改动(例如vue的nuxt,react的next) 丢失了部分SPA体验 node 容易成为性能瓶颈 方案二:构建时预渲染方案 在...
  • 数据库优化方案整理

    万次阅读 多人点赞 2018-08-29 16:05:16
    一:优化说明 A:有数据表明,用户可以承受的最大等待时间为8秒。数据库优化策略有很多,设计初期,建立好的数据结构对于后期性能优化至关重要。因为数据库结构是系统的基石,基础打不好,使用各种优化策略,也不能...
  • 数据库SQL优化大总结之 百万级数据库优化方案

    万次阅读 多人点赞 2016-06-23 09:43:50
    网上关于SQL优化的教程很多,但是比较杂乱。近日有空整理了一下,写出来跟大家分享一下,其中有错误和不足的地方,还请大家纠正补充。 这篇文章我花费了大量的时间查找资料、修改、排版,希望大家阅读之后,感觉好的...
  • 页面优化技术 页面缓存+URL缓存+对象缓存 由于并发瓶颈在数据库,想办法如何减少对数据库的访问,所以加若干缓存来提高,通过各种力度的缓存,最大力度页面缓存到最小力度的对象级缓存。 页面静态化,前后端分离 都...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 43,396
精华内容 17,358
关键字:

服务端缓存优化方案