天天看點

SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型

@[Toc]

一、Redis介紹

Redis是一種基于鍵值對(key-value)的NoSQL資料庫,與很多鍵值對 資料庫不同的是,Redis中的值可以是由string(字元串)、hash(哈希)、 list(清單)、set(集合)、zset(有序集合)、Bitmaps(位圖)、 HyperLogLog、GEO(地理資訊定位)等多種資料結構和算法組成,是以 Redis可以滿足很多的應用場景,而且因為Redis會将所有資料都存放在記憶體 中,是以它的讀寫性能非常驚人。不僅如此,Redis還可以将記憶體的資料利 用快照和日志的形式儲存到硬碟上,這樣在發生類似斷電或者機器故障的時 候,記憶體中的資料不會“丢失”。除了上述功能以外,Redis還提供了鍵過期、釋出訂閱、事務、流水線、Lua腳本等附加功能。總之,如果在合适的 場景使用好Redis,它就會像一把瑞士軍刀一樣所向披靡。

二、整合Redis

1、spring-boot-starter-data-redis介紹

Spring Boot 提供了對 Redis 內建的元件包:spring-boot-starter-data-redis,它依賴于 spring-data-redis 和lettuce。Spring Boot 1.0 預設使⽤的是 Jedis 用戶端,2.0 替換成了 Lettuce。

  • Lettuce:是⼀個可伸縮線程安全的 Redis 用戶端,多個線程可以共享同⼀個 RedisConnection,它利⽤優秀 Netty NIO 架構來⾼效地管理多個連接配接。
  • Spring Data:是 Spring 架構中的⼀個主要項⽬,⽬的是為了簡化建構基于 Spring 架構應⽤的資料通路,包括⾮關系資料庫、Map-Reduce 架構、雲資料服務等,另外也包含對關系資料庫的通路⽀持。
  • Spring Data Redis:是 Spring Data 項⽬中的⼀個主要子產品,實作了對 Redis 用戶端 API 的⾼度封裝,使對 Redis 的操作更加便捷。

2、引入依賴

建立一個SpringBoot項目,引入相關依賴:

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <!--使⽤ commons-pool 2 建立 Redis 連接配接池-->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>           

如果習慣使用Jdedis,也可以從spring-boot-stater-data-redis 排除 Lettuce ,使用Jedis :

<!--排除lettuce,使用jedis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <exclusions>
                <exclusion>
                    <groupId>io.lettuce</groupId>
                    <artifactId>lettuce-core</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
        </dependency>           

3、配置

3.1、application 配置

在application.properties中添加Redis相關配置:

# Redis
# Redis 資料庫索引(預設為 0)
spring.redis.database=0
# Redis 伺服器位址
spring.redis.host=localhost
# Redis 伺服器連接配接端⼝
spring.redis.port=6379 
# Redis 伺服器連接配接密碼(預設為空)
spring.redis.password=
# 連接配接池最⼤連接配接數(使⽤負值表示沒有限制) 預設 8
spring.redis.lettuce.pool.max-active=8
# 連接配接池最⼤阻塞等待時間(使⽤負值表示沒有限制) 預設 -1
spring.redis.lettuce.pool.max-wait=-1
# 連接配接池中的最⼤空閑連接配接 預設 8
spring.redis.lettuce.pool.max-idle=8
# 連接配接池中的最⼩空閑連接配接 預設 0
spring.redis.lettuce.pool.min-idle=0           

3.2、緩存配置

在自動配置類裡可以為 Redis 設定⼀些全局配置,⽐如配置主鍵的⽣産政策 KeyGenerator,如不配置會預設使⽤參數名作為主鍵。

@Configuration
//開啟緩存配置
@EnableCaching
public class RedisConfig {

    @Bean
    public KeyGenerator keyGenerator() {
        return new KeyGenerator() {
            @Override
            public Object generate(Object target, Method method, Object... params) {
                StringBuilder sb = new StringBuilder();
                sb.append(target.getClass().getName());
                sb.append(method.getName());
                for (Object obj : params) {
                    sb.append(obj.toString());
                }
                return sb.toString();
            }
        };
    }
}           

3.3、測試

在單元測試中,注⼊ RedisTemplate。String 是最常⽤的⼀種資料類型,普通的 key/value 存儲都可以歸為此類,value 其實不僅是 String 也可以是數字。

@RunWith(SpringRunner.class)
@SpringBootTest
public class RedisTest {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void testString() {
        redisTemplate.opsForValue().set("trytry", "it's time");
        Assert.assertEquals("it's time", redisTemplate.opsForValue().get("trytry"));
    }

}           

在這個單元測試中,我們使⽤ redisTemplate 存儲了⼀個字元串 "it's time",存儲之後擷取進⾏驗證,多次進⾏set 相同的 key,鍵對應的值會被覆寫。

綜上所述,進行使⽤ spring-boot-starter-data-redis隻需要上面的三步。

三、操作Redis各資料類型

Redis ⽀持多種資料類型,實體、哈希、清單、集合、有序集合,通過spring-boot-starter-data-redis都可以進行存儲、讀取、逾時失效、删除操作。

1、實體

建立一個實體類:

public class User implements Serializable {
    private String name;
    private String description;

    public User(String name, String description) {
        this.name = name;
        this.description = description;
    }
}           

将實體類放入緩存,再取出來:

@Test
    public void testModel(){
        User user=new User("zhangtiedan","頭鐵");
        //擷取一個操作對象
        ValueOperations<String, User> operations=redisTemplate.opsForValue();
        //将user存入緩存
        operations.set("tiedan", user);
        //取出緩存中的user
        User u=operations.get("tiedan");
        System.out.println("user: "+u.toString());
    }           

運作結果:

SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型

2、逾時失效

Redis 在存⼊每⼀個資料的時候都可以設定⼀個逾時時間,過了這個時間就會⾃動删除資料,這種特性⾮常适合我們對階段資料的緩存。

建立⼀個 User 對象,存⼊ Redis 的同時設定 100 毫秒後失效,設定⼀個線程暫停 1000 毫秒之後,判斷資料是否存在并列印結果。

@Test
    public void testExpire() throws InterruptedException {
        User user=new User("gangdan","人狠話不多");
        ValueOperations<String, User> operations=redisTemplate.opsForValue();
        //将user存⼊ Redis 的同時設定 100 毫秒後失效
        operations.set("expire", user,100, TimeUnit.MILLISECONDS);
        Thread.sleep(1000);
        boolean exists=redisTemplate.hasKey("expire");
        if(exists){
            System.out.println("exists is true");
        }else{
            System.out.println("exists is false");
        }
    }           
SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型

3、删除資料

删除資料也是必需的。

@Test
    public void testDelete(){
        User user=new User("hage","不慫但是沒什麼用");
        ValueOperations<String, User> operations=redisTemplate.opsForValue();
        //存入
        redisTemplate.opsForValue().set("deletekey", user);
        System.out.println("存入--是否存在:"+redisTemplate.hasKey("deletekey"));
        //删除
        redisTemplate.delete("deletekey");
        System.out.println("删除--是否存在:"+redisTemplate.hasKey("deletekey"));
    }           
SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型

4、Hash(哈希)

Redis 存儲⼀個 key會有⼀個最⼩記憶體,不管你存的這個鍵多⼩,都不會低于這個記憶體,是以合理的使⽤ Hash 可以幫我們節省很多記憶體。

在Redis中,哈希類型是指鍵值本身又是一個鍵值對 結構,形如value={{field1,value1},...{fieldN,valueN}}。

String和Hash的差別

SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型

Hash Set 就在哈希表 Key 中的域(Field)的值設為 value。如果 Key 不存在,⼀個新的哈希表被建立并進⾏ HSET 操作;如果域(field)已經存在于哈希表中,舊值将被覆寫。

@Test
    public  void  testHash(){
        HashOperations<String, Object, Object> hash = redisTemplate.opsForHash();
        hash.put("hash","you","you");
        String value=(String) hash.get("hash","you");
        System.out.println("hash value :"+value);
    }           
SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型

Hash set 的時候需要傳⼊三個參數,第⼀個為 key,第⼆個為 field,第三個為存儲的值。⼀般情況下 Key 代表⼀組資料,field 為 key 相關的屬性,⽽ value 就是屬性對應的值。

5、List

Redis List 的應⽤場景⾮常多,也是 Redis 最重要的資料結構之⼀。 使⽤ List 可以輕松的實作⼀個隊列,List 典型的應⽤場景就是消息隊列,可以利⽤ List 的 Push 操作,将任務存在 List 中,然後⼯作線程再⽤POP 操作将任務取出進⾏執⾏。

List push和pop示意圖

SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型
@Test
    public void testList() {
        ListOperations<String, String> list = redisTemplate.opsForList();
        list.leftPush("list","you");
        list.leftPush("list","go");
        list.leftPush("list","home");
        String value=(String)list.leftPop("list");
        System.out.println("list value :"+value.toString());
    }           
SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型

上面的例子上⾯的例⼦從左側插⼊⼀個 key 為 "list" 的隊列,然後取出左側最近的⼀條資料。List 有很多 API可以操作,⽐如從右側進⾏插⼊隊列從右側進⾏讀取,或者通過⽅法 range 讀取隊列的⼀部分。接着上⾯的例⼦使⽤ range 來讀取。

子清單擷取、删除等操作

SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型
List<String> values=list.range("list",0,2);
        for (String v:values){
            System.out.println("list range :"+v);
        }           
SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型

6、Set

集合(set)類型也是用來儲存多個的字元串元素,但和清單類型不一 樣的是,集合中不允許有重複元素,并且集合中的元素是無序的,不能通過 索引下标擷取元素。

集合類型示意圖

SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型
@Test
    public void testSet() {
        String key="set";
        SetOperations<String, String> set = redisTemplate.opsForSet();
        set.add(key,"kick");
        set.add(key,"you");
        set.add(key,"you");
        set.add(key,"now");
        Set<String> values=set.members(key);
        for (String v:values){
            System.out.println("set value :"+v);
        }
    }           
SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型

Redis 為集合提供了求交集、并集、差集等操作,可以⾮常⽅便的使⽤。

  • difference

difference() 函數會把 key 1 中不同于 key 2 的資料對⽐出來

@Test
    public  void  testDifference(){
        SetOperations<String, String> set = redisTemplate.opsForSet();
        String key1="setMore1";
        String key2="setMore2";
        set.add(key1,"it");
        set.add(key1,"you");
        set.add(key1,"you");
        set.add(key1,"know");
        set.add(key2,"xx");
        set.add(key2,"know");
        Set<String> diffs=set.difference(key1,key2);
        for (String v:diffs){
            System.out.println("diffs set value :"+v);
        }
    }           
SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型
  • unions

unions 會取兩個集合的合集。

@Test
    public void  testUnions(){
        SetOperations<String, String> set = redisTemplate.opsForSet();
        String key3="setMore3";
        String key4="setMore4";
        set.add(key3,"it");
        set.add(key3,"you");
        set.add(key3,"xx");
        set.add(key4,"aa");
        set.add(key4,"bb");
        set.add(key4,"know");
        Set<String> unions=set.union(key3,key4);
        for (String v:unions){
            System.out.println("unions value :"+v);
        }
    }           
SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型

7、ZSet

有序集合(ZSet)相對于哈希、清單、集合來說會有一點點陌生,但既然叫有序 集合,那麼它和集合必然有着聯系,它保留了集合不能有重複成員的特性, 但不同的是,有序集合中的元素可以排序。但是它和清單使用索引下标作為 排序依據不同的是,它給每個元素設定一個分數(score)作為排序的依據。

有序集合類型示意圖

SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型
@Test
    public void testZset(){
        String key="zset";
        redisTemplate.delete(key);
        ZSetOperations<String, String> zset = redisTemplate.opsForZSet();
        zset.add(key,"it's",1);
        zset.add(key,"your",6);
        zset.add(key,"show",4);
        zset.add(key,"time",3);
        Set<String> zsets=zset.range(key,0,3);
        for (String v:zsets){
            System.out.println("zset value :"+v);
        }
        Set<String> zsetB=zset.rangeByScore(key,0,3);
        for (String v:zsetB){
            System.out.println("zsetB value :"+v);
        }
    }           
SpringBoot整合Redis一、Redis介紹二、整合Redis三、操作Redis各資料類型

在實際開發中,不會給每⼀個使⽤的類都注⼊redisTemplate 來直接使⽤,⼀般都會對業務進⾏

簡單的包裝,最後提供出來對外使⽤。

參考:

【1】:《Spring Boot Vue全棧開發實戰》

【2】:《精通 Spring Boot 42 講》

【3】:《Redis開發和運維》

【4】:

Spring Boot(三):Spring Boot 中 Redis 的使用

【5】:

SpringBoot非官方教程 | 第九篇: springboot整合Redis

【6】:

spring-data-redis文檔