Redis介紹 && Java客戶端操作Redis

BruceZhang發表於2015-09-28

Redis介紹 && Java客戶端操作Redis


本文內容

  • redis介紹
  • redis的 shell 客戶端簡介
  • redis的 java 客戶端簡介

環境配置

  • redis 2.8.17 64bit
  • JDK1.6

redis介紹

  大多數時候,我們都將 redis 稱作是記憶體資料庫,它在執行過程中,將鍵值對資訊儲存在記憶體中,同時在後臺以非同步的形式寫入本地資料庫中(預設是:dump.rdb,在 redis.conf 中配置,如果需要考慮安全的持久化需求需要開啟 AOF 功能,詳細介紹可以檢視這篇文章 : redis持久化),redis中儲存的 key 可以是任意型別,最後都會儲存為 byte[] 型別;value 有多種型別 : string、list、set、sortedset、hash,基本上能夠滿足在開發中的鍵值儲存需求;此外,redis還支援事務、訊息系統等功能,而且提供了各種客戶端的 API,如 Java、Python、Shell 等等。

redis的 shell 客戶端簡介

  啟動 shell 客戶端之前,我們需要開啟 redis 服務,redis 預設埠是6379,這個配置也是位於 redis.conf 中。登陸 redis 客戶端的方法是 : redis-cli -h 127.0.0.1 -p 6379 (-h 是主機地址, -p 是 redis 服務埠號,由於本文介紹單機環境的 redis,我們可以直接採用預設的配置,那麼登陸的方式可以簡化為 : redis-cli),當我們開啟了 shell 客戶端之後,我們可以去 “Ping” 一下,如果返回 “PONG”,那麼代表 redis 服務是處於健康狀態的。
  Redis中每個資料庫對外都是一個從0開始的遞增數字命名,Redis預設支援16個資料庫,可以通過配置引數databases來修改這一數字。客戶端與Redis建立連線後會自動選擇0號資料庫,不過可以隨時使用SELECT命令更換資料庫。
  之前說過,redis 的 value 支援許多種型別,redis 對於每一種儲存型別都有不同的 shell 客戶端 api,這裡,我們對各種 value 的型別 api 進行介紹:

  • String型別
String api 功能描述
set(key, value) 給資料庫中名稱為key的string賦予值value
get(key) 返回資料庫中名稱為key的string的value
getset(key, value) 給名稱為key的string賦予上一次的value
mget(key1, key2,…, key N) 返回庫中多個string的value
setnx(key, value) 新增string,名稱為key,值為value
setex(key, time, value) 向庫中新增string,設定過期時間time
mset(key N, value N) 批量設定多個string的值
msetnx(key N, value N) 如果所有名稱為key i的string都不存在
incr(key) 名稱為key的string增1操作
incrby(key, integer) 名稱為key的string增加integer
decr(key) 名稱為key的string減1操作
decrby(key, integer) 名稱為key的string減少integer
append(key, value) 名稱為key的string的值附加value
substr(key, start, end) 返回名稱為key的string的value的子串

  • List型別
List api 功能描述
rpush(key, value) 在名稱為key的list尾新增一個值為value的元素
lpush(key, value) 在名稱為key的list頭新增一個值為value的 元素
llen(key) 返回名稱為key的list的長度
lrange(key, start, end) 返回名稱為key的list中start至end之間的元素
ltrim(key, start, end) 擷取名稱為key的list
lindex(key, index) 返回名稱為key的list中index位置的元素
lset(key, index, value) 給名稱為key的list中index位置的元素賦值
lrem(key, count, value) 刪除count個key的list中值為value的元素
lpop(key) 返回並刪除名稱為key的list中的首元素
rpop(key) 返回並刪除名稱為key的list中的尾元素
blpop(key1, key2,… key N, timeout) lpop命令的block版本
brpop(key1, key2,… key N, timeout) rpop的block版本

  • Set型別
List api 功能描述
sadd(key, member) 向名稱為key的set中新增元素member
srem(key, member) 刪除名稱為key的set中的元素member
spop(key) 隨機返回並刪除名稱為key的set中一個元素
smove(srckey, dstkey, member) 移到集合元素
scard(key) 返回名稱為key的set的基數
sismember(key, member) member是否是名稱為key的set的元素
sinter(key1, key2,…key N) 求交集
sunion(key1, (keys)) 求並集
sdiff(key1, (keys)) 求差集
sinterstore(dstkey, (keys)) 求交集並將交集儲存到dstkey的集合
sunionstore(dstkey, (keys)) 求並集並將並集儲存到dstkey的集合
sdiffstore(dstkey, (keys)) 求差集並將差集儲存到dstkey的集合
smembers(key) 返回名稱為key的set的所有元素
srandmember(key) 隨機返回名稱為key的set的一個元素

  • Hash型別
Hash api 功能描述
hset(key, field, value) 向名稱為key的hash中新增元素field
hget(key, field) 返回名稱為key的hash中field對應的value
hmget(key, (fields)) 返回名稱為key的hash中field i對應的value
hmset(key, (fields)) 向名稱為key的hash中新增元素field
hincrby(key, field, integer) 將名稱為key的hash中field的value增加integer
hexists(key, field) 名稱為key的hash中是否存在鍵為field的域
hdel(key, field) 刪除名稱為key的hash中鍵為field的域
hlen(key) 返回名稱為key的hash中元素個數
hkeys(key) 返回名稱為key的hash中所有鍵
hvals(key) 返回名稱為key的hash中所有鍵對應的value
hgetall(key) 返回名稱為key的hash中所有的鍵(field)及其對應的value

  除了針對 value 型別的 api 之外,還有一些常用的公共 api,如下:

常用 api 功能描述
quit 關閉連線(connection)
type(key) 返回值的型別
del(key) 刪除一個key
exists(key) 確認一個key是否存在
keys(pattern) 返回滿足給定pattern的所有key
dbsize 返回當前資料庫中key的數目
flushdb 刪除當前選擇資料庫中的所有key
flushall 刪除所有資料庫中的所有key

redis的 Java 客戶端簡介

  與 Shell 客戶端支援單機與叢集同一介面不同,Java 客戶端針對單機環境與叢集環境有不一樣的介面(單機環境使用 Jedis物件,叢集環境使用 JedisCluster 物件),本文針對單機環境進行介紹,叢集環境的話,除了配置下主機地址與埠號,其他的介面操作同 Jedis 是一樣的。
  下面對 redis 提供的 Java 客戶端介面進行介紹,由於程式碼中都有相應的註釋,所以,不做詳細描述:

  • 公共介面
    private static Jedis jedis;
    private static final String PREFIX = "qinyi-";
    private static final String HOST_IP = "127.0.0.1";
    private static final int HOST_PORT = 6379;
    private static final Logger logger = LoggerFactory.getLogger(RedisClient.class);

    public synchronized static Jedis getJedis(String host_ip, int host_port) {
        jedis = new Jedis(host_ip, host_port);
        //jedis.auth("root");  //開啟密碼驗證(配置檔案中為 requirepass root)的時候需要執行該方法

        return jedis;
    }

    public synchronized static Jedis getDefaultJedis() {
        return getJedis(HOST_IP, HOST_PORT);
    }

    /**
     *  清空 redis 中的所有資料
     * */
    public String flushRedis() {
        logger.debug("flush redis data");
        return getDefaultJedis().flushDB();
    }

    /**
     *  根據 pattern 獲取 redis 中的鍵
     * */
    public Set<String> getKeysByPattern(String pattern) {
        return getDefaultJedis().keys(pattern);
    }

    /**
     *  獲取 redis 中所有的鍵
     * */
    public Set<String> getAllKeys() {
        return getKeysByPattern("*");
    }

    /**
     *  判斷key是否存在redis中
     * */
    public boolean exists(String key) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().exists(PREFIX + key);
    }

    /**
     *  從Redis中移除一個key
     * */
    public void removeKey(String key) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        getDefaultJedis().del(PREFIX + key);
    }
  • String型別介面
    /**
     *  儲存字串
     * */
    public void setString(String key, String value, int expireTime) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }

        String finalKey = PREFIX + key;
        getDefaultJedis().set(finalKey, value);
        if (expireTime > 0) {
            /**
             *  如果設定了 expireTime, 那麼這個 finalKey會在expireTime秒後過期,那麼該鍵會被自動刪除
             *  這一功能配合出色的效能讓Redis可以作為快取系統來使用,成為了快取系統Memcached的有力競爭者
             * */
            getDefaultJedis().expire(finalKey, expireTime);
        }
    }

    /**
     *  獲取字串
     * */
    public String getString(String key) throws Exception{
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().get(PREFIX + key);
    }
  • List型別介面
    /**
     *  儲存 List
     * */
    public void pushList(String key, String value, String flag) throws Exception {
        if (StringUtil.IsEmpty(key) || StringUtil.IsEmpty(flag)) {
            logger.error("key or flag is null");
            throw new Exception("key or flag is null");
        }

        /**
         *  key代表的是連結串列的名字
         *  List是一個雙端連結串列,lpush是往連結串列的頭部插入一條資料,rpush是往尾部插入一條資料
         * */
        if (flag.equalsIgnoreCase("L")) {
            getDefaultJedis().lpush(PREFIX + key, value);
        } else if (flag.equalsIgnoreCase("R")) {
            getDefaultJedis().rpush(PREFIX + key, value);
        } else {
            logger.error("unknown flag");
            throw new Exception("unknown flag");
        }
    }

    /**
     *  獲取 List 中的單個元素
     * */
    public String popList(String key, String flag) throws Exception {
        if (StringUtil.IsEmpty(key) || StringUtil.IsEmpty(flag)) {
            logger.error("key or flag is null");
            throw new Exception("key or flag is null");
        }

        if (flag.equalsIgnoreCase("L")) {
            return getDefaultJedis().lpop(PREFIX + key);
        } else if (flag.equalsIgnoreCase("R")) {
            return getDefaultJedis().rpop(PREFIX + key);
        } else {
            logger.error("unknown flag");
            throw new Exception("unknown flag");
        }
    }

    /**
     *  獲取 List 中指定區間上的元素
     * */
    public List<String> getAppointedList(String key, long start, long end) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().lrange(PREFIX + key, start, end);
    }

    /**
     *  獲取 List 上所有的元素
     * */
    public List<String> getList(String key) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().lrange(PREFIX + key, 0, -1);
    }

    /**
     *  獲取 List 的長度
     * */
    public long getListLength(String key) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().llen(PREFIX + key);
    }
  • Set型別介面
    /**
     *  儲存 Set : 單值儲存
     * */
    public void addValueToSet(String key, String value) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        getDefaultJedis().sadd(PREFIX + key, value);
    }

    /**
     *  儲存 Set : 多值儲存
     * */
    public void addListToSet(String key, List<String> values) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        for (String value : values) {
            getDefaultJedis().sadd(PREFIX + key, value);
        }
    }

    /**
     * 刪除 Set 中的某個元素
     * */
    public void deleteElementInSet(String key, String value) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        getDefaultJedis().srem(PREFIX + key, value);
    }

    /**
     *  獲取 Set 中所有的成員
     * */
    public Set<String> getSet(String key) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().smembers(PREFIX + key);
    }

    /**
     *  判斷 value 是否屬於 set
     * */
    public boolean isExistInSet(String key, String value) throws Exception {
        if (StringUtil.IsEmpty(key) || StringUtil.IsEmpty(value)) {
            logger.error("key or value is null");
            throw new Exception("key or value is null");
        }
        return getDefaultJedis().sismember(PREFIX + key, value);
    }

    /**
     *  獲取 Set 中元素個數
     * */
    public long getLengthOfSet(String key) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().scard(PREFIX + key);
    }

    /**
     *  取兩個 Set 的交集
     * */
    public Set<String> getSetInter(String key1, String key2) throws Exception {
        if (StringUtil.IsEmpty(key1) || StringUtil.IsEmpty(key2)) {
            logger.error("key1 or key2 is null");
            throw new Exception("key1 or key2 is null");
        }
        return getDefaultJedis().sinter(PREFIX + key1, PREFIX + key2);
    }

    /**
     *  取兩個 Set 的並集
     * */
    public Set<String> getSetUnion(String key1, String key2) throws Exception {
        if (StringUtil.IsEmpty(key1) || StringUtil.IsEmpty(key2)) {
            logger.error("key1 or key2 is null");
            throw new Exception("key1 or key2 is null");
        }
        return getDefaultJedis().sunion(PREFIX + key1, PREFIX + key2);
    }

    /**
     *  取兩個 Set 的差集
     * */
    public Set<String> getSetDiff(String key1, String key2) throws Exception {
        if (StringUtil.IsEmpty(key1) || StringUtil.IsEmpty(key2)) {
            logger.error("key1 or key2 is null");
            throw new Exception("key1 or key2 is null");
        }
        return getDefaultJedis().sdiff(PREFIX + key1, PREFIX + key2);
    }
  • SortedSet型別介面
    /**
     *  儲存有序集合 SortedSet
     * */
    public void setSortedSet(String key, double weight, String value) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        getDefaultJedis().zadd(PREFIX + key, weight, value);
    }

    /**
     *  獲取有序集合指定區間上的元素
     * */
    public Set<String> getAppointedSortedSet(String key, long start, long end) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().zrange(PREFIX + key, start, end);
    }

    /**
     *  獲取有序集合上的所有元素
     * */
    public Set<String> getSortedSet(String key) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().zrange(PREFIX + key, 0, -1);
    }

    /**
     *  獲取有序集合上某個權重區間上的元素
     * */
    public long getLengthOfSortedSetByWeight(String key, double min, double max) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().zcount(PREFIX + key, min, max);
    }

    /**
     *  刪除有序集合上的元素
     * */
    public void deleteElementInSortedSet(String key, String value) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        getDefaultJedis().zrem(PREFIX + key, value);
    }

    /**
     *  獲取有序集合中元素的個數
     * */
    public long getLengthOfSortedSet(String key) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().zcard(PREFIX + key);
    }

    /**
     *  檢視有序集合中元素的權重
     * */
    public double getWeight(String key, String value) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().zscore(PREFIX + key, value);
    }
  • Hash型別介面
    /**
     *  儲存 HashMap
     * */
    public void setHashMapByFieldAndValue(String key, String field, String value) throws Exception {
        if (StringUtil.IsEmpty(key) || StringUtil.IsEmpty(field)) {
            logger.error("key or field is null");
            throw new Exception("key or field is null");
        }
        getDefaultJedis().hset(PREFIX + key, field, value);
    }

    /**
     *  儲存 HashMap
     * */
    public void setHashMapByMap(String key, Map<String, String> map) throws Exception {
        if (StringUtil.IsEmpty(key) || map == null) {
            logger.error("key or map is null");
            throw new Exception("key or map is null");
        }
        getDefaultJedis().hmset(PREFIX + key, map);
    }

    /**
     *  刪除 HashMap 中的鍵值對
     * */
    public void deleteHashMapValueByField(String key, String field) throws Exception {
        if (StringUtil.IsEmpty(key) || StringUtil.IsEmpty(field)) {
            logger.error("key or field is null");
            throw new Exception("key or field is null");
        }
        getDefaultJedis().hdel(PREFIX + key, field);
    }

    /**
     *  獲取 HashMap 中鍵對應的值
     * */
    public String getHashMapValueByField(String key, String field) throws Exception {
        if (StringUtil.IsEmpty(key) || StringUtil.IsEmpty(field)) {
            logger.error("key or field is null");
            throw new Exception("key or field is null");
        }
        return getDefaultJedis().hget(PREFIX + key, field);
    }

    /**
     *  獲取 HashMap 中所有的 key
     * */
    public Set<String> getHashMapKeys(String key) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().hkeys(PREFIX + key);
    }

    /**
     *  獲取 HashMap 中所有的值
     * */
    public List<String> getHashMapValues(String key) throws Exception {
        if (StringUtil.IsEmpty(key)) {
            logger.error("key is null");
            throw new Exception("key is null");
        }
        return getDefaultJedis().hvals(PREFIX + key);
    }

    /**
     *  判斷 HashMap 中是否存在某一個鍵
     * */
    public boolean isFieldExistsInHashMap(String key, String field) throws Exception {
        if (StringUtil.IsEmpty(key) || StringUtil.IsEmpty(field)) {
            logger.error("key or field is null");
            throw new Exception("key or field is null");
        }
        return getDefaultJedis().hexists(PREFIX + key, field);
    }

  相對關係型資料庫而言,redis 以一種非常簡單的思想來儲存資料,由於它將資料儲存在記憶體中,所以,讀寫非常高效,同時,它將記憶體中的資料寫入資料庫中,保證資料不會丟失,每次關閉並重新開啟時,再將儲存在本地資料庫中的鍵值對資訊載入記憶體。
  redis 同時提供 Windows 和 Linux 系統的不同版本,針對不同的流行語言都有相應的 API 介面(目前來看, Java 最為活躍),方便了開發過程中的使用。
  一些經典的資料庫操作,redis 中都有很好的支援,比如保證一致性的事務,減小構建資料庫開銷的連線池介面(JedisPool)等等。
  總的來說,使用 redis,你會感受到它的簡潔與高效!

相關文章