对于使用http4s、Argonaut和Slick在Redis中缓存JSON响应的Scala应用程序,我有如下内容,并希望确认它的工作方式是我所期望的。这样做的想法是,如果没有找到Redis key,那么调用给定的fallback方法从原始源(MySQL)获取数据,并为将来的请求缓存数据,否则跳过MySQL:
/** 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)))但是,不管Redis中是否有数据,上面的代码总是会打印"getThingsFromDatabase“,因为getThingsFromDatabase(12)在作为参数调用时会执行。在Redis中,原始数据库似乎没有按预期被击中(如果它被关闭的话没有错误)。我认为这是因为在这个场景中没有使用fallback未来,所以即使执行了该方法,它也没有完成。
如果将fallback: Future[Seq[Thing]]更改为按名称调用(即fallback: => Future[Seq[Thing]]),则"getThingsFromDatabase“仅在缓存为空时(如预期的那样)第一次打印,因为fallback仅在None()条件下调用,而不是作为参数执行。
虽然后者是预期的功能,但如果在println方法中没有getThingsFromDatabase,那么原始版本和按名调用版本之间会有区别吗?如果Redis有所需的数据,两者似乎都满足了不去MySQL的需要,尽管前者执行了该方法,但两者都没有真正完成未来。
发布于 2017-03-21 21:59:44
会有很大的差异。如前所述,将调用db.run(),数据库将执行查询;结果可能会被丢弃,但通常情况下,服务器将完成所有工作。
如果things是一个大的、未编入索引的表,或者该代码经常被调用,那么是的,您可能会看到不必要的调用会显著降低性能。这个例子是一个海报-孩子的有用的调用的名字.
https://stackoverflow.com/questions/42938738
复制相似问题