Redisを触ってみる その1

# 目的
とても便利そうなRedisさんを扱えるように基本的な操作を一通り試してみる。
最終的にplayframework（Java）上でRedisを利用したチャット的なものを作ってみる。

## 環境
* OS: Windows7 Professional 64bit
* 言語・フレームワーク: Java/playframework
* ライブラリ: Jedis（諸事情によりplayのPluginは使わない）

## とりあえず環境構築
1. Windows用Redisをダウンロード。 https://github.com/MSOpenTech/redis
2. 後はbin/releaseの中のredis-server.exeを実行するだけ。
3. playframework（Java）で適当にプロジェクトを作って、sbtにJedisを依存ライブラリとして記載してコンパイル。

```:build.sbt
libraryDependencies ++= Seq(
  "org.webjars" %% "webjars-play" % "2.2.2",
  "org.webjars" % "bootstrap" % "2.3.1",
  "redis.clients" % "jedis" % "2.6.0")
```

## Redisの基本操作
### Redisへの接続
とりあえずRedisへの接続を扱う内部メソッドを適当に作って、他の操作を行うメソッドから呼ぶ形にだけしておく。

```java:RedisClient.java
package redisUtil;

import com.google.common.base.Strings;
import redis.clients.jedis.*;

public class RedisClient {

    JedisPool pool;

    // Jedisの各メソッドの戻り値（文字列）判別用
    public enum RedisResult {
        OK("OK"), 
        NG("NG");
	    
        private final String name;
        private RedisResult(final String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return this.name;
        }
    }

    public RedisClient(){}

    // Redisへの接続を取得
    private Jedis getResource() throws JedisConnectionException
    {
        synchronized (this) {
            if(pool == null || pool.isClosed())
            {
                pool = new JedisPool(new JedisPoolConfig(), "localhost");
            }
        }

        return pool.getResource();
    }

    // Redisへの接続を返却
    private void returnResource(Jedis jedis) throws JedisConnectionException
    {
        pool.returnResource(jedis);
    }
}
```
### 基本的な操作いろいろ
単純な操作を一通り試してみる。

```java:RedisClient.java
public void testRedis()
{
    String resultString = "";
    Boolean resultBoolean;
    Long resultLong;

    Jedis jedis = getResource();

    // Keyを登録
    System.out.print("set(\"testKey\", \"testValue\"):");
    resultString = jedis.set("testKey", "testValue");
    System.out.println(resultString);

    // Keyの存在確認
    System.out.print("exists(\"testKey\", \"testValue\"):");
    resultBoolean = jedis.exists("testKey");
    System.out.println(resultBoolean);

    // Keyを参照
    System.out.print("get(\"testKey\"):");
    resultString = jedis.get("testKey");
    System.out.println(resultString);

    // Keyを有効期限付きで登録
    System.out.print("setex(\"testKey\", 600, \"expireValue\"):");
    resultString = jedis.setex("testKey", 600, "expireValue");
    System.out.println(resultString);

    // 3秒待機
    System.out.println("Thread.sleep(3000)......");
    try { Thread.sleep(3000);}
    catch (InterruptedException e) {e.printStackTrace();}

    // Keyの有効期限を取得
    System.out.print("ttl(\"testKey\"):");
    resultLong = jedis.ttl("testKey");
    System.out.println(resultLong);

    // Keyの有効期限を変更
    System.out.print("expire(\"testKey\", 800, \"expireValue\"):");
    resultLong = jedis.expire("testKey", 800);
    System.out.println(resultLong);

    // Keyの有効期限を取得
    System.out.print("ttl(\"testKey\"):");
    resultLong = jedis.ttl("testKey");
    System.out.println(resultLong);

    // Keyの削除
    System.out.print("del(\"testKey\"):");
    resultLong = jedis.del("testKey");
    System.out.println(resultLong);

    // Keyの存在確認
    System.out.print("exists(\"testKey\", \"testValue\"):");
    resultBoolean = jedis.exists("testKey");
    System.out.println(resultBoolean);

    // Keyが存在しなければ登録する。
    System.out.print("setnx(\"testKey\", \"testValueBefore\"):");
    resultLong = jedis.setnx("testKey", "testValueBefore");
    System.out.println(resultLong);

    // Keyが存在しなければ登録する。
    System.out.print("setnx(\"testKey\", \"testValueAfter\"):");
    resultLong = jedis.setnx("testKey", "testValueAfter");
    System.out.println(resultLong);

    // Keyを参照
    System.out.print("get(\"testKey\"):");
    resultString = jedis.get("testKey");
    System.out.println(resultString);

}
```

```:実行結果
set("testKey", "testValue"):OK
exists("testKey", "testValue"):true
get("testKey"):testValue
setex("testKey", 600, "expireValue"):OK
Thread.sleep(3000)......
ttl("testKey"):597
expire("testKey", 800, "expireValue"):1
ttl("testKey"):800
del("testKey"):1
exists("testKey", "testValue"):false
setnx("testKey", "testValueBefore"):1
setnx("testKey", "testValueAfter"):0
get("testKey"):testValueBefore
```

各メソッドの戻り値がちょっとアレなのでその辺は実際に作る時に少し苦労するかも。。。
また今回は使う予定がないので試してないけど、mset()を使用すれば単一アトミック操作も可能らしい。

## 次回やること
pub/subの動作確認