2017-03-21 93 views
3

我有類似以下的內容,用於在Redis中爲使用http4s,Argonaut和Slick的Scala應用程序緩存JSON響應,並且想確認它的工作方式如何。我們的想法是,如果一個Redis的key沒有被發現,然後打電話給定fallback方法從原始來源(MySQL的)獲取數據並緩存以備將來的請求,否則跳過的MySQL:是否需要調用Future方法參數「by-name」?

/** Get from MySQL */ 
def getThingsFromDatabase(matchingId: Int): Future[Seq[Thing]] = { 
    println("getThingsFromDatabase") 
    val query = things.filter(_.fieldId === matchingId) 
    db.run(query.result) 
} 

/** Get from Redis, else MySQL via `fallback` */ 
def getThingsFromRedisOrDatabase(key: String, 
           fallback: Future[Seq[Thing]]): 
           Future[argonaut.Json] = { 
    val stored = redis.get(key) 
    stored match { 
    // Data exists, return from redis 
    case Some(s) => { 
     Parse.parse(s) match {   // convert string to Json 
     case Right(r) => Future { r } // Json => Future[argonaut.Json] 
     case Left(l) => println(l) // error 
     } 
    } 
    // Data does not exist, get from database and store 
    case None() => { 
     val data = fallback.map(_.toList.asJson) 
     data map { redis.set(key, _) } 
     data // Future[argonaut.Json] 
    } 
    } 
} 

// GET /things/12 
Ok(getThingsFromRedisOrDatabase("things:12", getThingsFromDatabase(12))) 

然而這工作,上述代碼將始終打印「getThingsFromDatabase」,無論Redis中是否存在數據,因爲getThingsFromDatabase(12)在作爲參數調用時執行。正如預期的那樣,原始數據庫似乎沒有用Redis中的數據命中(如果它關閉,則沒有錯誤)。我認爲這是因爲fallback未來在這種情況下沒有被使用,所以即使該方法被執行也不會完成。

如果fallback: Future[Seq[Thing]]改爲調用 - 名稱(即fallback: => Future[Seq[Thing]]),「getThingsFromDatabase」僅印刷在第一時間時,高速緩存爲空,如所預期的,因爲fallback被稱爲僅在None()條件和不執行作爲參數。

而後者則是預期的功能,會有原來,被呼叫的名稱版本之間的差異,如果沒有在getThingsFromDatabase方法println?如果Redis具有所需的數據,兩者似乎都可以滿足不去MySQL的需要,即使前者執行該方法,也不能實際完成Future。

回答

5

會有顯着的區別。正如所寫,db.run()將被調用,並且數據庫將執行查詢;結果可能會被丟棄,但通常服務器將完成所有工作。

如果things是一個很大的無索引表,或者如果經常調用此代碼,那麼是的,您可能會看到來自不必要調用的顯着性能下降。這個例子是通過名稱實用的招貼畫。

相關問題