在Scala应用程序中缓存Cassandra表

时间:2018-07-13 12:48:32

标签: scala concurrency cassandra

我需要从Cassandra获取一些数据,以用于Kafka-Streams流应用程序中的条目。我需要对ID执行联接。我想设置一个缓存以节省查询时间。 该表很简单: id | name ---|----- 1 |Mike

我的计划很简单:从数据库中查询表,然后存储到Map[Int, String]中。
主要问题是-表中的数据可能会更改,并且需要定期更新,因此我需要不时查询它。

到目前为止,我已经提出了这样的线程解决方案:

    // local database mirror
    class Mirror(user: String, password: String) extends Runnable {

      var database: Map[Int, String] =  Map[Int, String]() withDefaultValue "undefined"

      def run(): Unit = {
        update()
      }


      // 
      def update(): Unit = {
        println("update")
        database.synchronized {
          println("sync-update")        
          // val c = Driver.getConnection(...)
          // database = c.execute(select id, name from table). ...
          database += (1 -> "one")
          Thread.sleep(100)
          // c.close()
        }
      }

      def get(k: Int): Option[String] = {
        println("get")
        database.synchronized {
          println("sync-get")
          if (! (database contains k)) {
            update()
            database.get(k)
          } else {
            database.get(k)
          }
        }      
      }
    }

主要内容如下:

    def main(args: Array[String]): Unit = {

      val db = new Mirror("u", "p")
      val ex = new ScheduledThreadPoolExecutor(1)
      val f = ex.scheduleAtFixedRate(db, 100, 100, TimeUnit.SECONDS)       

      while(true) { // simulate stream
        val res = db.get(1)
        println(res)
        Thread.sleep(10000)
      }       
    }

似乎功能正常。但是我的代码有什么陷阱吗?尤其是我对updateget函数的线程安全性没有信心。

1 个答案:

答案 0 :(得分:0)

如果您不反对使用Akka,请看Akka Streams。具体来说Alpakka来做到这一点。如果没有必要,则无需重新发明轮子。

话说回来,代码有以下问题:

  1. 如果Cassandra中的条目已更新,则对缓存的存在性检查将无济于事。只有当您的缓存中缺少它们时,它才有帮助
  2. 如果您认为大多数时候您的缓存将具有 current 条目,请考虑使用reentrant read write lock。如果您有多个线程调用镜像,这将有助于争用。

再次,我强烈建议您使用Alpakka来查看Akka Streams,因为您可以使用该工具来完成所需的工作,而不必自己编写大量代码。