高并发之缓存的特征和应用

  • 缓存的特征
  • 命中率:命中数/(命中数 + 没有命中数),命中率越高产生收益也就越高,性能也就越好,相应的也就越短,吞吐量也就越高,抗并发的能力也就越强
  • 最大元素(空间):缓存中科院存放的最大元素的数量,当缓存的数量超过了缓存空间,则会触发缓存清空策略
  • 清空策略:
  • FIFO先进先出策略,先进入的优先清除,
  • LFU最少使用策略,对比命中数,
  • LRU最近最少使用策略,
  • 过期时间,
  • 随机等等。
  • 缓存的分类和应用场景
  • 本地缓存:Guava Cache,SpringMVC本地缓存,Mybatis二级缓存
  • 分布式缓存:Memceche,Redis
  • Guava Cache缓存的基本使用
  • 如果cache,get("key1"),是去查询缓存如果没有命中的话就去调用load方法

高并发之缓存的特征和应用


  • 高并发场景缓存会出现的问题
  • 缓存的一致性
  • 更新数据库成功---更新缓存失败
  • 更新缓存成功---更新数据库失败
  • 更新数据库成功---淘汰缓存失败
  • 淘汰缓存成功---更新数据库失败
  • 缓存并发
  • 并发时请求缓存时已过期或者没有命中或者更新的情况下有大量的请求访问数据库,
  • 解决办法:在缓存更新或者过期的情况下,先尝试获取到lock,当更新完成后,尝试释放锁,其他的请求只需要牺牲一定的等待时间
  • 缓存穿透
  • 在高并发的场景下,如果某一个key被高并发的访问没有被命中,出于对容错性的考虑会尝试从后端的数据库获取,从而导致大量的请求访问了数据库,主要是当key对应的数据为空或者为null的情况下,
  • 解决方法:
  • .对查询结果为空的对象也进行缓存,如果是集合可以缓存一个空的集合,而不是null,如果是单个对象可以通过字段标识来区分,(实现相对简单)
  • 对所有可能对应数据为空的key进行统一的存放,并在请求前做拦截(实现相对复杂)
  • 缓存雪崩现象
  • 以上都有可能导致缓存雪崩,还有缓存周期性的时效也有可能导致缓存的雪崩,可以通过设置不同的过期时间来避免缓存失效
  • 高并发缓存之Redis缓存的应用
  • 应用场景之汇率显示,各个国家的汇率是不同的,而且时刻都在改变,那么如何动态的实时显示数据呢?首先我们的数据来源第三方接口,当调用第三方接口推送给我们的数据需要进行数据清洗,然后利用利用GuavaCache 缓存最近几分钟内所有汇率的分时数据,key是数据的时间单位到分钟,通过小时跟分钟缓存每个国家汇率的分时数据,当一分钟有多次推送时,将原有的缓存进行覆盖,这样每个国家的汇率每分钟只会缓存一条数据,然后启动一个定时任务,每分钟将最近几分钟里面的数据写入到Redis里面,使用Hash结构,key也是分时数据的小时和分钟
  • 应用场景之运动排名实时更新,以轻加APP中活动模块的排名实现为例,每位用户参加完运动都会进行计算消耗的卡路里,第一步是入库,入库成功然后在保存当前用户的运动数据到Redis,key为用户ID+运动方案ID,同时使用Redis的ZADD函数加入到Redis的有序集合中会自动根据value进行排序,如果已经有了就会替换最新,如果想获取指定区间内的排名,比如前50,则可以用ZRANGE函数获取,更多的实现请参考http://redisdoc.com。
  • 应用场景之分布式session,正常单机的架构不存在session丢失的问题,但是在分布式架构中,session共享就是个问题,因为当你第一次请求时有可能在第一台服务器,第二次时由于负载均衡策略会跑到其他服务器执行请求,这样第一次的请求session就丢失了,如何让一台服务器的session在另一台上也能共享?这里还是用到redis了,当我们登录时验证用户账号密码都正确的情况下,通过twitter的snoflke算法实现分布式ID作为token然后以token为key,用户信息作为value存储到redis,同时将token存储到cookie保存登录状态,这样做的好处是在分布式的环境中服务器之间的数据需要时间同步,这样就会有延迟,就有可能导致session不一致,使用redis就能解决不一致的问题。
  • 高并发缓存之页面缓存
  • 页面缓存通常采用模板引擎,比如springboot推荐的freemark,thymeleaf,等等,换句话说也就是做页面静态化处理,接口数据通过接口从后端获取,实现前后端分离静态页面无需连接数据库打开速度会明显提高, 另外一种是通过手动渲染得到HTML然后缓存到redis,不过常用的实现方式也是最直接的是采用模板引擎

高并发之缓存的特征和应用

相关推荐