完美取代hashmap,SpringBoot整合Redis快取DB資料

2022-01-10 11:00:02

一、百度百科

redis是一個key-value儲存系統。和Memcached類似,它支援儲存的value型別相對更多,包括string(字串)、list(連結串列)、set(集合)、zset(sorted set --有序集合)和hash(雜湊型別)。這些資料型別都支援push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支援各種不同方式的排序。與memcached一樣,為了保證效率,資料都是快取在記憶體中。區別的是redis會週期性的把更新的資料寫入磁碟或者把修改操作寫入追加的記錄檔案,並且在此基礎上實現了master-slave(主從)同步。

Redis 是一個高效能的key-value資料庫。 redis的出現,很大程度補償了memcached這類key/value儲存的不足,在部 分場合可以對關聯式資料庫起到很好的補充作用。它提供了Java,C/C++,C#,PHP,JavaScript,Perl,Object-C,Python,Ruby,Erlang等使用者端,使用很方便。

Redis支援主從同步。資料可以從主伺服器向任意數量的從伺服器上同步,從伺服器可以是關聯其他從伺服器的主伺服器。這使得Redis可執行單層樹複製。存檔可以有意無意的對資料進行寫操作。由於完全實現了釋出/訂閱機制,使得從資料庫在任何地方同步樹時,可訂閱一個頻道並接收主伺服器完整的訊息釋出記錄。同步對讀取操作的可延伸性和資料冗餘很有幫助。

二、Redis下載

在這裡插入圖片描述

三、Linux中安裝Redis

1、上傳、解壓

Redis一般安裝在Linux環境下,開啟虛擬機器器,通過xftp將redis壓縮包上傳到Linux伺服器,並進行解壓。
在這裡插入圖片描述

2、修改redis.conf組態檔,使其在後臺啟動

在這裡插入圖片描述

四、Java呼叫redis

1、匯入pom

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.2.0</version>
</dependency>

2、編寫Java主方法

呼叫Redis中的ping方法,驚現異常:
在這裡插入圖片描述
(1)開始的時候以為是防火牆的問題,後來通過檢視redis狀態發現IP地址不對,不應該是127.0.0.1
在這裡插入圖片描述
(2)修改redis.conf
在這裡插入圖片描述
注意:需要注意的是在修改redis.conf時,①注掉bind 127.0.0.1;②需要將本機存取保護模式設定為no

3、再次執行主方法,執行成功!

在這裡插入圖片描述

五、五巨量資料型別程式碼範例

package com.guor.redis;
 
import redis.clients.jedis.Jedis;
 
import java.util.List;
import java.util.Set;
 
public class JedisTest01 {
    public static void main(String[] args) {
        test05();
    }
 
    private static void test01(){
        Jedis jedis = new Jedis("192.168.194.131", 6379);
        String value = jedis.ping();
        System.out.println(value);
        //新增
        jedis.set("name","GooReey");
        //獲取
        String name = jedis.get("name");
        System.out.println(name);
 
        jedis.set("age","30");
        jedis.set("city","dalian");
        //獲取全部的key
        Set<String> keys = jedis.keys("*");
        for(String key : keys){
            System.out.println(key+" --> "+jedis.get(key));
        }
 
        //加入多個key和value
        jedis.mset("name1","zs","name2","ls","name3","ww");
        List<String> mget = jedis.mget("name1", "name2");
        System.out.println(mget);//[zs, ls]
    }
 
    //list
    private static void test02(){
        Jedis jedis = new Jedis("192.168.194.131", 6379);
        jedis.lpush("key1","01","02","03");
        List<String> values = jedis.lrange("key1",0,-1);
        System.out.println(values);//[03, 02, 01]
    }
 
    //set
    private static void test03(){
        Jedis jedis = new Jedis("192.168.194.131", 6379);
        jedis.sadd("username","zs","ls","ww");
        Set<String> names = jedis.smembers("username");
        System.out.println(names);//[ww, zs, ls]
    }
 
    //hash
    private static void test04(){
        Jedis jedis = new Jedis("192.168.194.131", 6379);
        jedis.hset("users","age", "20");
        String hget = jedis.hget("users","age");
        System.out.println(hget);
    }
 
    //zset
    private static void test05(){
        Jedis jedis = new Jedis("192.168.194.131", 6379);
        jedis.zadd("china",100d,"shanghai");
        Set<String> names = jedis.zrange("china",0,-1);
        System.out.println(names);//[shanghai]
    }
}

六、手機驗證碼功能程式碼範例

package com.guor.redis;
 
import redis.clients.jedis.Jedis;
 
import java.util.Random;
 
public class PhoneCode {
    public static void main(String[] args) {
        verifyCode("10086");//795258
        getRedisCode("10086","795258");//success.
    }
 
    //1、生成6位數位驗證碼
    public static String getCode(){
        Random random = new Random();
        String code = "";
        for (int i = 0; i < 6; i++) {
            int rand = random.nextInt(10);
            code += rand;
        }
        return code;//849130
    }
 
    //2、每個手機每天只能傳送三次,驗證碼放到redis中,設定過期時間
    public static void verifyCode(String phone){
        Jedis jedis = new Jedis("192.168.194.131", 6379);
        //拼接key
        //手機傳送次數key
        String countKey = "VerifyCode" + phone + ":count";
        //驗證碼key
        String codeKey = "VerifyCode" + phone + ":code";
        //每個手機每天只能傳送三次
        String count = jedis.get(countKey);
        if(count == null){
            //設定過期時間
            jedis.setex(countKey,24*60*60,"1");
        }else if(Integer.parseInt(count)<=2){
            //傳送次數+1
            jedis.incr(countKey);
        }else if(Integer.parseInt(count)>2){
            System.out.println("今天的傳送次數已經超過三次");
            jedis.close();
        }
 
        String vCode = getCode();
        jedis.setex(codeKey,120,vCode);
        jedis.close();
    }
 
    //3、驗證碼校驗
    public static void getRedisCode(String phone, String code){
        //從redis中獲取驗證碼
        Jedis jedis = new Jedis("192.168.194.131", 6379);
        //驗證碼key
        String codeKey = "VerifyCode" + phone + ":code";
        String redisCode = jedis.get(codeKey);
        if(redisCode.equals(code)){
            System.out.println("success.");
        }else{
            System.out.println("error");
        }
        jedis.close();
    }
}

在這裡插入圖片描述
當超過三次時:
在這裡插入圖片描述

七、SpringBoot整合Redis

1、建工程,引入pom

在這裡插入圖片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.guor</groupId>
    <artifactId>redisspringboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>redisspringboot</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
 
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-redis -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
            <version>2.4.5</version>
        </dependency>
 
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
            <version>2.9.0</version>
        </dependency>
 
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
 
</project>

2、設定類

(1)application.properties

# Redis資料庫索引(預設為0)
spring.redis.database=0
# Redis伺服器地址
spring.redis.host=192.168.194.131
# Redis伺服器連線埠
spring.redis.port=6379
# Redis伺服器連線密碼(預設為空)
spring.redis.password=
# 連線池最大連線數(使用負值表示沒有限制)
spring.redis.jedis.pool.max-active=20
# 連線池最大阻塞等待時間(使用負值表示沒有限制)
spring.redis.jedis.pool.max-wait=-1
# 連線池中的最大空閒連線
spring.redis.jedis.pool.max-idle=10
# 連線池中的最小空閒連線
spring.redis.jedis.pool.min-idle=0
# 連線超時時間(毫秒)
spring.redis.timeout=1000

(2)RedisConfig

package com.guor.redisspringboot.config;
 
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.cache.RedisCacheWriter;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.*;
 
import java.time.Duration;
 
@EnableCaching
@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory factory) {
        RedisTemplate<String, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(factory);
 
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
//        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
        jackson2JsonRedisSerializer.setObjectMapper(om);
 
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
        // key採用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // hash的key也採用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // value序列化方式採用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);
        // hash的value序列化方式採用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
 
    /**
     * 基於SpringBoot2 對 RedisCacheManager 的自定義設定
     * @param redisConnectionFactory
     * @return
     */
    @Bean
    public RedisCacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
        //初始化一個RedisCacheWriter
        RedisCacheWriter redisCacheWriter = RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory);
        //設定CacheManager的值序列化方式為json序列化
        RedisSerializer<Object> jsonSerializer = new GenericJackson2JsonRedisSerializer();
        RedisSerializationContext.SerializationPair<Object> pair = RedisSerializationContext.SerializationPair.fromSerializer(jsonSerializer);
        RedisCacheConfiguration defaultCacheConfig = RedisCacheConfiguration.defaultCacheConfig().serializeValuesWith(pair);
 
        //設定預設超過時期是1天
        defaultCacheConfig.entryTtl(Duration.ofDays(1));
        //初始化RedisCacheManager
        return new RedisCacheManager(redisCacheWriter, defaultCacheConfig);
    }
}

3、控制類測試

package com.guor.redisspringboot.controller;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
@RequestMapping("/redisTest")
public class RedisTestController {
 
    @Autowired
    private RedisTemplate redisTemplate;
 
    @GetMapping
    public String getRedis(){
        redisTemplate.opsForValue().set("name","zs");
        String name = (String) redisTemplate.opsForValue().get("name");
        return name;
    }
}

在這裡插入圖片描述