spray-caching缓存结果

来源:互联网 发布:手机淘宝投诉电话多少 编辑:程序博客网 时间:2024/05/23 13:20

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,具体的就自已配置了

 



 

 

0 0
原创粉丝点击