Redis 功能入门大全和基于scala实现示例(2)

2019-03-06  本文已影响10人  小赵营
redis-scala.PNG

概要

  • Redis server 基于5.0.0的stable版本
  • Client基于 Jedis 2.9.0
  • Scala 基于 2.11.X

文章链接:

Redis 功能入门大全和基于scala的应用实现(1)

本文内容:

如何访问Redis数据?

Redis基础功能是数据读写和数据复制机制,除此之外包含运维工具、性能提升pipeline、事务于Lua脚本等。'Redis服务读写是主体功能。'

使用Hash散列表对数据进行读写,结合jedis 和 scala代码说明不同读写方式方法。
本节描述使用jedis对redis服务进行读写操作,不同模式下Redis读写API基本相同,因此后面不在说明。

Redis服务端只提供读写服务,访问数据则需要客户端。开源组件有多款软件支持redis访问,Jedis是我们访问redis服务的客户端。

scala是如何现实不同方式的读写哪?下面逐步说明:

在数据操作上,Redis服务端hash类型数据处理API是统一的,即不同的服务类型对数据操作API一致。因此,scala实现读写操作所有模式都相同,不同模式编码层面的差异在于redis连接创建和释放。

 //using 功能是获取连接,执行完成后,关闭连接
 trait Using{
  type Close = {def close():Unit} //定义新的类型

  def using[T <: Close,M](pa: T)(f:T => M): Unit = {
    f(pa)
    pa.close()
  }
}
//按照key读取数据
   def readHGet(keys: List[String]) = {
    using(connection) {
      conn =>
        keys.foreach {
          el => conn.hgetAll(el)
        }
    }
  }
  //读取所有key
  def readKeys = {
    using(connection) {
      conn =>
       conn.keys("*")
    }
  }
//使用pipeline的方式对数据进行读写
  def readPipeline(keys: List[String]): Unit = {
    using(connection) {
      conn =>
      val p = conn.pipelined()
      keys.foreach {
        el => p.hgetAll(el)
      }
      p.sync()
    }
  }
//对数据的写入操作,获取的jedis连接没有关闭连接
trait RedisAction  {
 //多个hash数据写入
 def writeHMset(data: List[(String, util.HashMap[String, String])], conn: Jedis) = {
    data.foreach {
      case (key, data)  =>
        conn.hmset(key, data)
    }
  }
//使用pipeline方式写入数据
def pipelineHash(data: List[(String, util.HashMap[String, String])], conn: Jedis) = {
    val p = conn.pipelined()
    data.foreach {
      case (key, dt) =>
        p.hmset(key, dt)
    }
    p.sync() //without response
  }

//without watch/unwatch
//使用事务方式写数据
def transactionHash(data: List[(String, util.HashMap[String, String])], conn: Jedis) = {
    val t: Transaction = conn.multi()
    data.foreach {
      case (key, data)  =>
        t.hmset(key, data)
    }
    t.exec()
  }
}

jedis操作没有保证数据数据一致,因此以上redis数据读写接口在单一的客户端使用正常。多客户端并发读写会存在数据不一致的情况。这需要 Redis分布式锁解决,见后面章节。

  • [ src]# ./redis-server ../redis_6380.conf slaveof 127.0.0.1 6380
    1410:C 05 Nov 2018 15:54:06.132 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
    1410:C 05 Nov 2018 15:54:06.132 # Redis version=5.0.0, bits=64, commit=00000000, modified=0, pid=1410, just started
    1410:C 05 Nov 2018 15:54:06.132 # Configuration loaded
    1410:S 05 Nov 2018 15:54:06.133 # Creating Server TCP listening socket 127.0.0.1:6380: bind: Address already in use

rebind port

原因: redis.conf中存在bind参数,指定能够访问本机的IP.在创建实例是不是绑定的127.0.01导致异常,改成绑定IP即可。

  • 创建连接池失败 默认密码不能为空,否则 使用该接口创建失败

jedis Caused by: java.net.SocketTimeoutException: Read timed out

原因:

JedisPool(conf, host, port, timeOut, password, database, clientName, true)

ssh 安全连接设置不能为true, 密码不能为空.

redis.clients.jedis.exceptions.JedisDataException: Please close pipeline or multi block before calling this method.

原因:Redis事务的执行结果是在exec之后才统一返回,所以Jedis会用一个Response对象最为事务对象transaction的执行放回值。如果我们在transaction执行exec方法之前调用response对象的get方法会出现异常。

上一篇下一篇

猜你喜欢

热点阅读