Redis基本使用一(數據結構常用命令)

開發工具:

  1. Redis3.2;
  2. IDEA;
  3. JDK11;
  4. Gradle4.8;

使用數據結構常用命令:

1.創建項目,開啓Redis服務端,導入相關座標;

重要座標如下:

implementation('org.springframework.boot:spring-boot-starter-data-redis')
// Redis客戶端,用於執行數據結構常用命令
implementation('redis.clients:jedis:2.9.0')

2.添加配置類(SpringBoot默認自動配置,沒有特殊需求則可以省略);

配置類代碼如下:

package com.lsm1998.redis.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import redis.clients.jedis.JedisPoolConfig;

/**
 * 作者:劉時明
 * 日期:2018/11/12
 * 時間:21:13
 * 說明:
 */
@Configuration
public class RedisConfig
{
    @Bean
    public RedisTemplate initRedisTemplate()
    {
        JedisPoolConfig poolConfig = new JedisPoolConfig();
        // 最大空閒數
        poolConfig.setMaxIdle(5);
        // 最大連接數
        poolConfig.setMaxTotal(30);
        // 最大等待毫秒數
        poolConfig.setMaxWaitMillis(1000 * 20);
        // 連接工廠
        JedisConnectionFactory factory=new JedisConnectionFactory(poolConfig);
        // 後初始化方法
        factory.afterPropertiesSet();
        // 序列化器
        //RedisSerializer jdkSerializer=new JdkSerializationRedisSerializer();
        RedisSerializer stringSerializer=new StringRedisSerializer();
        // 定義RedisTemplate,設置連接工廠
        RedisTemplate redisTemplate=new RedisTemplate();
        redisTemplate.setConnectionFactory(factory);
        // 設置序列化器
        redisTemplate.setDefaultSerializer(stringSerializer);
        redisTemplate.setKeySerializer(stringSerializer);
        redisTemplate.setValueSerializer(stringSerializer);
        redisTemplate.setHashKeySerializer(stringSerializer);
        redisTemplate.setHashValueSerializer(stringSerializer);
        return redisTemplate;
    }
}

3.具體程序如下:

package com.lsm1998.redis.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.BinaryClient;
import redis.clients.jedis.Jedis;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * 作者:劉時明
 * 日期:2018/11/12
 * 時間:21:49
 * 說明:Redis基本數據類型
 */
@RestController
public class TestController
{
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 字符數據的常用命令
     *
     * @return
     */
    @GetMapping("test1")
    public Object test1()
    {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        // 設置鍵值對
        jedis.set("str_1", "新恆結衣");
        // 返回值的字符長度
        System.out.println("值的長度=" + jedis.strlen("str_1"));
        // 獲取值
        System.out.println("str_1=" + jedis.get("str_1"));

        // 刪除鍵值對
        //jedis.del("str_1");

        // 修改值,並返回新值
        String str = jedis.getSet("str_1", "泰勒斯威夫特");
        System.out.println("str_1舊值=" + str);
        System.out.println("str_1新值=" + jedis.get("str_1"));

        // 獲取子串
        System.out.println("str_1子串=" + jedis.getrange("str_1", 0, jedis.strlen("str_1") / 2));

        // 追加字符,只支持末尾追加
        jedis.append("str_1", "-Red");
        System.out.println("str_1=" + jedis.get("str_1"));

        // 字節數組組成的鍵值對
        jedis.getSet("str_2".getBytes(), "新恆結衣".getBytes());
        System.out.println("str_2=" + jedis.get("str_2".getBytes()));

        // 關閉連接
        jedis.close();
        return "ok";
    }

    /**
     * 字符數據的計算命令
     *
     * @return
     */
    @GetMapping("test2")
    public Object test2()
    {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        jedis.set("num", "0");
        System.out.println("num=" + jedis.get("num"));
        // 指定key值自增
        jedis.incr("num");
        System.out.println("num=" + jedis.get("num"));
        // 指定增加
        jedis.incrBy("num", 10L);
        System.out.println("num=" + jedis.get("num"));
        // 指定key值自減
        jedis.decr("num");
        System.out.println("num=" + jedis.get("num"));
        // 指定減少
        jedis.decrBy("num", 5L);
        System.out.println("num=" + jedis.get("num"));
        // 操作浮點數,此方法沒有對應的decrByFloat方法,只需加一個負號即可取得相同效果
        jedis.incrByFloat("num", 3.14);
        System.out.println("num=" + jedis.get("num"));
        jedis.incrByFloat("num", -3.14);
        System.out.println("num=" + jedis.get("num"));
        // 關閉連接
        jedis.close();
        return "ok";
    }

    /**
     * 哈希結構的常用命令
     *
     * @return
     */
    @GetMapping("test3")
    public Object test3()
    {
        HashOperations hashOperations = redisTemplate.opsForHash();
        // 指定一個key
        String key = "hash";
        // 一個key下保存多個鍵值對
        hashOperations.put(key, "k1", "新恆結衣");
        hashOperations.put(key, "k2", new byte[1024]);
        try
        {
            // 此處會拋出異常
            hashOperations.put(key, "k3", new Object());
        } catch (Exception e)
        {
            System.err.println("該對象不可以被序列化");
        }

        // Jedis操作哈希數據結構,與HashOperations有一定區別
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        // jedis.hset保存的是field+value,而與HashOperations則是hashKey+value
        jedis.hset(key, "j1", "泰勒斯威夫特");
        // 編譯錯誤,只支持字符串類型
        //jedis.hset(key, "j2", new ArrayList<>());

        System.out.println("當前大小=" + hashOperations.size(key));
        // 通過遍歷key來輸出所有的鍵值對
        hashOperations.keys(key).forEach(k -> System.out.println("key=" + k + ",value=" + hashOperations.get(key, k)));
        return hashOperations.get(key, "k1");
    }

    /**
     * 有序集合結構的常用命令
     *
     * @return
     */
    @GetMapping("test4")
    public Object test4()
    {
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        String key = "key";
        // 添加元素,key-value-score形式,score代表分數,用於排序
        zSetOperations.add(key, 59, 2.5);
        zSetOperations.add(key, new String("新恆結衣"), 3.0);

        ZSetOperations.TypedTuple<Object> typedTuple1 = new DefaultTypedTuple<>("牛頓", 100.0);
        ZSetOperations.TypedTuple<Object> typedTuple2 = new DefaultTypedTuple<>("伯努利", 98.0);
        Set<ZSetOperations.TypedTuple<Object>> typedTupleSet = new HashSet<>();
        typedTupleSet.add(typedTuple1);
        typedTupleSet.add(typedTuple2);
        // 添加元素,key-Set形式
        zSetOperations.add(key, typedTupleSet);

        long size = zSetOperations.zCard(key);
        // 此時應該有4個元素,因爲key-Set其底層會拆爲key-value-score形式
        System.out.println("元素個數=" + size);

        // 獲取所有元素
        Set temp = zSetOperations.range(key, 0, size - 1);
        long count = zSetOperations.count(key, 80, 100);
        System.out.println("分數80到100之間元素個數=" + count);
        // 返回分數80到100之間的元素集合
        // Set temp = zSetOperations.rangeByScore(key, 80, 100);
        // 刪除元素,可以同時傳入多個值
        zSetOperations.remove(key, 59);
        // 根據分數範圍進行刪除
        // zSetOperations.removeRangeByScore(key,80,100);
        temp.forEach(e -> System.out.println(e));

        // Jedis操作ZSet類型
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        jedis.zadd(key, -10.0, "hello");
        Set temp2 = jedis.zrevrange(key, 0, jedis.zcard(key) - 1);
        System.out.println("**********華麗的分隔線**********");
        // 此時長度爲1
        // 與HashOperations相似,Jedis操作的ZSet和ZSetOperations操作的ZSet是有區別的,二者不能混用
        System.out.println("長度=" + jedis.zcard(key));
        temp2.forEach(e -> System.out.println(e));

        // 計算多個有序集合的並集
        String destKey = "dest_key";
        // 添加一個同value同score的元素
        redisTemplate.opsForZSet().add(destKey, "新恆結衣", 3.0);
        // 添加一個同value但不同score的元素
        redisTemplate.opsForZSet().add(destKey, "新恆結衣", 3.1);
        // 此處結果與unionAndStore(key, key, destKey)一致,結果返回3,代表有3個value相同的元素
        long l = zSetOperations.unionAndStore(key, destKey, destKey);
        System.out.println("相同value元素數量=" + l);
        return "ok";
    }

    /**
     * 鏈表結構
     *
     * @return
     */
    @GetMapping("test5")
    public Object test5()
    {
        /**
         * Jedis操作鏈表
         */
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        String key = "j_key";
        // 左端插入
        jedis.lpush(key, "左一", "左二", "左三");
        // 右端插入
        jedis.rpush(key, "右一", "右二", "右三");
        // 下標獲取
        System.out.println("鏈表頭部元素=" + jedis.lindex(key, 0));
        // 最右側刪除
        jedis.rpop(key);
        // 最左側刪除
        jedis.lpop(key);
        // 更新元素
        jedis.lset(key, 1, "新值");
        // 嘗試最左側插入,如果key不存在則失敗,返回0
        long result = jedis.lpushx(key + "007", "嘗試");
        System.out.println("result=" + result);
        // 從左到右刪除1個value爲‘右二’的元素,0則代表所有
        jedis.lrem(key, 1, "右二");
        // 元素插入,指定BEFORE或者AFTER和元素
        jedis.linsert(key, BinaryClient.LIST_POSITION.AFTER, "新值", "插隊元素");
        // 鏈表裁剪,只保留下標0到5的,裁剪後長度必爲end-strrt+1,如果少了則循環補值
        jedis.ltrim(key, 0, 5);
        // 打印0到5的節點值,此時數據爲[左二, 新值, 插隊元素, 新值, 插隊元素, 新值],奇怪的是頭元素不會補值
        System.out.println(jedis.lrange(key, 0, 5));
        System.out.println("jedis鏈表長度=" + jedis.llen(key));
        // 阻塞命令,試圖刪除最左側元素,如果沒有則等待,直到刪除成功或者超時,並返回key和被刪除的元素
        List<String> list = jedis.blpop(10 * 1000, key);
        System.out.println("list=" + list);

        /**
         * ListOperations操作鏈表
         * 寫多了就會發現redisTemplate包裝類和jedis操作的功能大體一致,但效果不互通
         */
        ListOperations listOperations = redisTemplate.opsForList();
        // 刪除前兩個‘hello’
        listOperations.remove(key, 2, "hello");
        System.out.println("redisTemplate包裝類鏈表長度=" + listOperations.size(key));
        return "ok";
    }

    /**
     * Set結構
     *
     * @return
     */
    @GetMapping("test6")
    public Object test6()
    {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        String key = "j_key";
        // 插入元素,由於是散列結構,重複元素會覆蓋
        jedis.sadd(key, "新恆結衣", "Aragaki", "新恆結衣");
        // 統計個數
        System.out.println("元素個數=" + jedis.scard(key));
        // 判斷元素是否存在
        System.out.println("一個元素是否存在?" + jedis.sismember(key, "新恆結衣"));
        // 獲取所有鍵
        Set<String> keys = jedis.keys(key);
        keys.forEach(e -> System.out.println(e));
        // 獲取所有值
        jedis.smembers(key).forEach(e -> System.out.println(e));
        // 隨機彈出一個元素
        System.out.println(jedis.spop(key));

        SetOperations setOperations = redisTemplate.opsForSet();
        setOperations.add("key_1", "e1", "e2", "e3");
        setOperations.add("key_2", "e0", "e1", "e2");
        // 求差集
        setOperations.difference("key_1", "key_2").forEach(e -> System.out.println(e));
        // 求並集
        setOperations.intersect("key_1", "key_2").forEach(e -> System.out.println(e));
        return "ok";
    }

    /**
     * 基數結構
     *
     * @return
     */
    @GetMapping("test7")
    public Object test7()
    {
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        // 添加一個元素
        jedis.pfadd("key", "新恆結衣");
        // 返回基數值
        System.out.println("基數值=" + jedis.pfcount("key"));
        // 保存多個基數值
        jedis.pfmerge("key2", "新恆結衣", "Aragaki");

        HyperLogLogOperations hyperLogLogOperations = redisTemplate.opsForHyperLogLog();
        hyperLogLogOperations.add("key", "新恆結衣");
        hyperLogLogOperations.size("key");
        hyperLogLogOperations.delete("key");
        return "ok";
    }
}

 

Redis的6種數據結構總結:

  1. 有兩種不同的方式可以操作數據,Jedis客戶端執行與redisTemplate包裝類均有類似的操作方法,但操作的數據不互通;
  2. 都可以實現基本的增刪改查;
  3. 除了Hash結構和鏈表結構外,其餘結構都具有一定的運算支持,自增或者求並集等;
  4. 基數類型是最晦澀難懂的,他的原理是壓縮數據,將重複的數據轉爲不重複的基數,減少內存佔用;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章