spray-caching缓存结果

1.想一想,如果我们有一个操作是非常耗时,而结果是不变的,或者结果变化的程度不大且可以延时出现(结果),那么我们没有必要重复性的去做这件事情

或者在一定时间将结果进行复用,使用画画来看看

我们假设黑线上的红点是原本要访问的时间点,然而但每次结果的差异不大时我们就可以复用上一次的结果,例子博客发表的帖数不到5以上就不显示,所以我们画出绿色的间隔表示,t1,t2,t3,t4,t5表示缓存间隔,也就是根据设置我们可以把t1的结果用在t2上,或者t3用在t5上

这样就减少cpu的负担

 

实际用处,例如我们有个商城,每秒有500个用户点击,每次点击即读取数据库,然而在500次在一秒内的结果是差异不大的,那么我们就可以归为一次就够了,这样就大大减少cpu的负担

 添加依赖

name:="demo7"


resolvers += "spray repo" at "http://repo.spray.io"

libraryDependencies ++= Seq(
  "com.typesafe.akka"     % "akka-actor_2.10"   % "2.3.12" withSources() withJavadoc(),
  "io.spray"              % "spray-util"        % "1.2.1" withSources() withJavadoc(),
  "io.spray"              % "spray-caching"     % "1.2.1" withSources() withJavadoc(),
  "org.scalatest"         % "scalatest_2.10"    % "2.2.2" withSources() withJavadoc(),
  "org.specs2"            %% "specs2"           % "1.12.3" withSources() withJavadoc(),
  "com.googlecode.concurrentlinkedhashmap"      % "concurrentlinkedhashmap-lru" % "1.4" withSources() withJavadoc()
)

 

1.假设我们有个运算是非常复杂的,我们想要一定程度上复用他,为社么叫一定程度呢?因为我们用key来标记,想要复用他就往内存找出这个key对应的值

 

  def expensiveOp(): Double = new util.Random().nextDouble()

Actor相关

  val system = ActorSystem();

  import system.dispatcher


2.创建结果类型对应的cache

  val cache: Cache[Double] = LruCache()

3.

  def cacheOp[T](key: T): Future[Double] = cache.apply(key) {
    expensiveOp()
  }

注意这里的key即对应结果的,如果key找不到就再次运算expensiveOp

测试

class AppTest extends Specification{

  "cacheing operation" should {
    """cacheOp must be Equal""" in{
       val a =  Demo.cacheOp("foo").await
       val b =  Demo.cacheOp("foo").await
       a must_==(b)
    }
    """cacheOp must be NoEqual""" in{
      val a =  Demo.cacheOp("foo1").await
      val b =  Demo.cacheOp("foo2").await
      a must_!=(b)
    }
  }
}


觉得很不错吧,当然我们是使用LruCache创建的该策略是SimpleLruCache

<p>  def apply[V](maxCapacity: Int = 500,
               initialCapacity: Int = 16,
               timeToLive: Duration = Duration.Inf,
               timeToIdle: Duration = Duration.Inf): Cache[V] = {
    //#
    def check(dur: Duration, name: String) =
      require(dur != Duration.Zero,
        s"Behavior of LruCache.apply changed: Duration.Zero not allowed any more for $name parameter. To disable " +
          "expiration use Duration.Inf instead of Duration.Zero")
    // migration help
    check(timeToLive, "timeToLive")
    check(timeToIdle, "timeToIdle")</p><p>    if (timeToLive.isFinite() || timeToIdle.isFinite())
      new ExpiringLruCache[V](maxCapacity, initialCapacity, timeToLive, timeToIdle)
    else
      new SimpleLruCache[V](maxCapacity, initialCapacity)
  }</p>

也就是时间不限制的!就是我们key对应的值永久存在内存中的!这样对于一些情况不不好的,例如当该操作是数据库读取的时候,我们要抛弃一些时间点的数据,如5分钟读取前的数据就不要了,那么我们可以通过另一个策略ExpiringLruCache,具体的就自已配置了

 



 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值