Giter Club home page Giter Club logo

redis-client-scala-netty's Introduction

Redis scala client library Build Status

Features

  • binary safe values
  • really asynchronous calls without any thread pools
  • protocol pipelining
  • connection multiplexing
  • in-memory redis implementation which can come in handy for testing (in active development)
  • scala 2.11, 2.12 support

Changes from original version:

  • added support of scripting commands
  • moved to scala futures
  • binary safe requests encoding
  • moved to sbt
  • in-memory client
  • Distributed lock implementation (Redlock)
  • Netty 4.1.x

Building

$ sbt package

Unit tests assume redis is running on localhost on port 6379, THEY WILL FLUSH ALL DATA!

Instalation

Add to build.sbt

resolvers += Resolver.bintrayRepo("yarosman", "maven")  
libraryDependencies ++= Seq(
    "com.impactua" %% "redis-scala" % "2.0.0"
)

Example usage with scala REPL

    import com.impactua.redis.RedisClient

    val r = RedisClient("redis://:db_password@localhost:6379")

    // basic

    r.set("foo", "bar")
    r.get[String]("foo") // get method has to be typed, hints at implicit conversion

    // lists
    r.lpush("ll", "l1")
    r.lpush("ll", "l2")
    r.lrange[String]("ll", 0, 100)
    r.lpop[String]("ll")

    // sets
    r.sadd("ss", "foo")
    r.sadd("ss", "bar")
    r.smembers[String]("ss")

For convenience any API method has both synchronous and asynchronous versions:

    import com.impactua.redis.RedisClient
    val r = RedisClient("redis://localhost")
    val fooFuture = r.getAsync[String]("foo")

    val future = r.lpopAsync[String]("ll") // prefetch data

Synchronous methods by default wait up to 1 minute for the future to complete, but one can specify duration on client initialization:

    import com.impactua.redis.RedisClient
    import scala.concurrent.duration._

    val r = RedisClient("redis://localhost", timeout = 20 seconds)

Dealing with Lua scripts:

    import com.impactua.redis.RedisClient
    val r = RedisClient("redis://localhost")
    
    val resultsList = r.eval[Int]("return ARGV[1];", ("anyKey", "2"))
    val scriptHash = r.scriptLoad("return ARGV[1];")
    val evalResultsList = r.evalsha[Int](scriptHash, ("key", "4"))

Hyper Log Log:

    import com.impactua.redis.RedisClient
    val r = RedisClient("redis://localhost")
    val anyAddedH1 = r.pfadd("h1", "a", "b", "c", "d") // true
    val anyAddedH2 = r.pfadd("h2", "a", "b", "f", "g") // true
    val count = r.pfcount("h1") // 4

    r.pfmerge("merge-result", "h1", "h2")
    val mergeCount = r.pfcount("merge-result") // 6

Sharding example:

    import com.impactua.redis.{RedisCluster, RedisClient}

    val shardingHashFunc = (s:String) => s.hashCode // shard on string values
    val cluster = new RedisCluster[String](shardingHashFunc, "redis://localhost:6379" /*, more redis hosts */)

    val r = cluster("egusername") // get redis client

Example of adding custom conversion objects

Conversion is implemented using BinaryConverter interface.

    import com.google.protobuf.{CodedOutputStream,CodedInputStream}

    implicit val intProtobufConverter = new BinaryConverter[Int]() {
        def read(data: BinVal) = {
            val is = CodedInputStream.newInstance(b)
            is.readInt32()    
        }

        def write(v: Int) = {
            val barr = new Array[Byte](CodedOutputStream.computeInt32SizeNoTag(i))
            val os = CodedOutputStream.newInstance(barr)
            os.writeInt32NoTag(i)
            barr
        }
    }

Conversion objects can be passed explicitly:

    r.set("key-name", 15)(intProtobufConverter)

In-memory client usage

It is not necessary now to run a standalone Redis server for development or unit tests, simply changing host name can force client to perform all operations in memory. Also it is possible to emulate several databases at once. The behavior is similar to in-memory databases in popular embeddable RDMS like H2 or HyperSQL. Following code creates an in-memory database test:

    val r = RedisClient("redis-mem://test")

Note: feature is in active development so not all operations are supported now.

Redlock usage

Redlock is a distributed lock implementation on multiple (or one) redis instances based on algorithm described (here). Usage example:

    import com.impactua.redis.primitives.Redlock
    
    val redlock = Redlock("redis://192.168.2.11", "redis://192.168.2.12", "redis://192.168.2.13")

    val lock = redlock.lock("resource-name", ttl = 60)

    if(lock.successful) {
        /* Some code that has to be executed only on one instance/thread. */
    }

One have to specify some name common for all application instances. In case of success lock method returns object that contains resource name and some random value that should be used to unlock resource:

    redlock.unlock(lock)

Manual unlocking is not always necessary as lock will be unlocked automatically on Redis server after ttl seconds will pass.

Also there is convenient withLock method:

    val redlock = Redlock("redis://192.168.2.15")
    redlock.withLock("resource-name") {
        /* Some code that has to be executed only on one instance/thread. */
    }

Redlock is fully supported by in-memory client.

Contributing

Any contributions or suggestions are welcome. Feel free to start a discussion in issues or create a pull request.

Thanks to @yarosman and @FayazSanaulla for their contributions.

redis-client-scala-netty's People

Contributors

fsanaulla avatar sergkh avatar yarosman avatar

Stargazers

 avatar

Watchers

 avatar

redis-client-scala-netty's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.