• Spring Boot 2.x(十四):整合Redis,看这一篇就够了


    Redis简介

    Redis 是一个开源的使用 ANSI C 语言编写、遵守 BSD 协议、支持网络、可基于内存亦可持久化的日志型、Key-Value 数据库,并提供多种语言的 API非关系型数据库(NoSQL)

    Redis的特性

    1. Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
    2. 性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
    3. 原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
    4. 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

    Redis的应用

    1. 会话缓存
    2. 数据缓存
    3. 排行榜/计数器
    4. 消息队列

    Redis的数据类型

    • String: 字符串
    • Hash: 散列
    • List: 列表
    • Set: 集合
    • Sorted Set: 有序集合

    Redis的部署

    PS: 我这里是基于Mac环境,Windows环境下的同学可以安装Linux虚拟机同步进行操作。

    1. 官网下载 Stable(稳定)版本

    1. 找到下载的文件,解压并编译
    tar -zxvf redis-5.0.4.tar.gz
    mv redis-5.0.4 /usr/local/
    cd /usr/local/redis-5.0.4/
    make test
    

    执行到这里,最好先执行一遍make test,确保编译可以通过,需要大概三分钟。
    到这个就说明测试通过了。我们接着往下执行

    make
    cd src/
    make install
    

    执行到这里安装就算是告一段落了,接下来我们进行redis的一些配置:

    vim ../redis.conf
    

    找到136行左右的daemonize将其属性改为yes,可以让redis在后台运行,然后找到500行左右的requirepass,后面输入我们需要设置的密码,这样就可以通过密码来访问redis了。
    然后我们通过指定配置文件的方式来启动redis

    ./redis-server ../redis.conf
    

    执行完事儿之后,查看是否执行成功:

    ps -ef | grep redis
    

    可以看到,我们的redis已经启动成功了,然后通过rdm来访问一下:

    大功告成,现在万事俱备,只欠东风。我们下面来看一下在Spring Boot中怎么使用redis吧。

    在Spring Boot中的使用

    Spring Boot给我们提供了现成的spring-boot-starter-data-redis,我们只需要在pom文件中将之导入即可。

    		<dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <!-- 创建连接池 -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
            </dependency>
    

    然后,我们需要在配置文件中配置一些有关redis的信息:

    spring:
      redis:
        host: 127.0.0.1  # IP
        port: 6379  # 端口号
        password: 123456  # 密码
        lettuce:
          pool:
            max-active: 8 # 连接池最大连接数
            max-wait: -1ms  # 连接池最大阻塞等待时间(使用负值表示没有限制)
            min-idle: 0 # 连接池中的最小空闲连接
            max-idle: 8 # 连接池中的最大空闲连接
    

    接下来,我们需要对我们所需要的Redis的操作给封装到一个接口中,方便我们去调用,这里我基于接口,抽象类,实现类的结构实现了一套Redis的方法,需要的同学可以去GitHub上下载(子项目名称:viboot-rds),GitHub的地址在文末。这里仅仅贴出接口的部分方法

    package com.itframe.dao;
    
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    /**
     *
     */
    public interface RedisDao {
    
    	/**
    	 * 判断缓存中是否有对应的value
    	 * 
    	 * @param key
    	 * @return boolean
    	 */
    	public boolean existsKey(Object key);
    
    	/**
    	 * 根据key获取key列表(key值可为模糊匹配---taskInfo:taskDetail:* <---> *代表任意字符)
    	 * 
    	 * @param pattern
    	 * @return Set<Object>
    	 */
    	public Set<Object> keys(Object pattern);
    
    	/**
    	 * 根据key删除对应的value
    	 * 
    	 * @param key
    	 */
    	public boolean delete(Object key);
    
    	/**
    	 * 根据key获取个数
    	 * 
    	 * @param key
    	 */
    	public int count(Object key);
    
    	/**
    	 * 批量删除对应的value
    	 * 
    	 * @param keys
    	 */
    	public void delete(String[] keys);
    
    	/**
    	 * 批量删除key(key值可为模糊匹配---taskInfo:taskDetail:* <---> *代表任意字符)
    	 * 
    	 * @param pattern
    	 */
    	public long deletePattern(Object pattern);
    
    	/**
    	 * 批量删除对应的value
    	 * 
    	 * @param keys
    	 */
    	public long delete(Set<Object> keys);
    
    	/**
    	 * 写入缓存(操作字符串)
    	 * 
    	 * @param key
    	 * @param value
    	 * @return boolean
    	 */
    	public boolean vSet(Object key, Object value);
    
    	/**
    	 * 写入缓存设置时效时间(操作字符串)
    	 * 
    	 * @param key
    	 * @param value
    	 * @return boolean
    	 */
    	public boolean vSet(Object key, Object value, Long expireTime);
    
    	/**
    	 * 更新写入缓存设置时效时间(操作字符串)
    	 * 
    	 * @param key
    	 * @return boolean
    	 */
    	public boolean vSetUpdate(Object key, Long expireTime);
    
    	/**
    	 * 读取缓存(操作字符串)
    	 * 
    	 * @param key
    	 * @return Object
    	 */
    	public Object vGet(Object key);
    
    	/**
    	 * 哈希 添加(操作hash)
    	 * 
    	 * @param key
    	 * @param hashKey
    	 * @param value
    	 */
    	public void hmSet(Object key, Object hashKey, Object value);
    
    	/**
    	 * 哈希 添加(操作hash)
    	 * 
    	 * @param key
    	 * @param map
    	 */
    	public void hmSetAll(Object key, Map<Object, Object> map);
    
    	/**
    	 * 哈希获取数据(操作hash)
    	 * 
    	 * @param key
    	 * @return Map<Object, Object>
    	 */
    	public Map<Object, Object> hmGet(Object key);
    
    	/**
    	 * 哈希获取数据(操作hash)
    	 * 
    	 * @param key
    	 * @param hashKey
    	 * @return Object
    	 */
    	public Object hmGet(Object key, Object hashKey);
    
    	/**
    	 * 哈希删除数据(操作hash)
    	 * 
    	 * @param key
    	 * @param hashKey
    	 * @return Object
    	 */
    	public Object hmDel(Object key, Object hashKey);
    
    }
    

    抽象类中我们进行了RedisTemplate的初始化以及序列化:

    public abstract class AbstractBaseRedisDao<K, V> {
    
    	@Resource(name = "redisTemplate")
    	protected RedisTemplate<K, V> redisTemplate;
    
    	/**
    	 * 设置redisTemplate
    	 * 
    	 * @param redisTemplate
    	 */
    	public void setRedisTemplate(RedisTemplate<K, V> redisTemplate) {
    		this.redisTemplate = redisTemplate;
    	}
    
    	/**
    	 * 获取 RedisSerializer
    	 */
    	protected RedisSerializer<String> getRedisSerializer() {
    		return redisTemplate.getStringSerializer();
    	}
    }
    

    在实现类中我们通过操作RestTemplate来实现接口中的方法~

    Redis缓存实战

    首先,我们如果想在Spring Boot项目中启用缓存,需要在启动类上加上注解@EnableCaching,这个是重点,要记住了!

    首先介绍一下注解三剑客:@Cacheable @CachePut@CacheEvict

    • @Cacheable:主要针对方法配置,能够根据方法的请求参数对其进行缓存,常用于查询操作
    • @CachePut:主要针对方法配置,能够根据方法的请求参数对其进行缓存,常用于修改操作
    • @CacheEvict:清空缓存,主要用于删除操作。

    下面我们来看一下用法:

    
    	/**
    	 *	value: 缓存的名称
    	 *	key: 缓存的键
    	 *	return 缓存的值
    	 */ 
    	@Override
        @Cacheable(value = "users", key = "#id")
        public UserDO findOne(Long id) {
        	// 如果我们第二次访问的时候,控制台没有打印出这句话说明是从缓存中取出
            log.info("From MYSQL");
            return userMapper.get(id);
        }
    
        @Override
        @CachePut(value = "users", key = "#userDO.id")
        public UserDO update(UserDO userDO) {
        	// 执行之后,再次访问findOne的时候,应当没有打印出“From MySQL”,且返回的是我们修改后的值,说明这一步缓存成功
            if (userMapper.update(userDO) > 0) {
                return userMapper.get(userDO.getId());
            }
            return null;
        }
    
        @Override
        @CacheEvict(value = "users", key = "#id")
        public int delete(Long id) {
        	// 执行之后去rdm中查看即可
            return userMapper.delete(id);
        }
    

    测试1

    第一次访问findOne

    第二次访问findOne:

    仍然是刚刚的结果,但是控制台没有打印出任何东西,说明缓存成功


    测试2

    调用update后再次调用findOne:

    可以看出信息已被修改且未访问数据库


    测试3

    访问delete,查看rdm:

    说明删除成功~

    源码地址

    Github
    Gitee

    记得顺手点个star,您的肯定是对我写作最大的动力!

    公众号

    原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知

  • 相关阅读:
    再战CS231-数组的访问
    win10定时关机
    再战CS231-快速排序
    数据库权限
    numpy
    anaconda
    控件的相对位置与绝对位置-UI界面编辑器(SkinStudio)教程
    共用字体-UI界面编辑器(SkinStudio)教程
    添加图片按钮-UI界面编辑器(SkinStudio)教程
    为窗体设置背景图片-UI界面编辑器(SkinStudio)教程
  • 原文地址:https://www.cnblogs.com/viyoung/p/10576137.html
Copyright © 2020-2023  润新知