SpringBoot中的Redis 缓存问题及操作方法

目录
  • 1、五大基本数据类型和操作
    • 1.1 字符串-string
    • 1.2 列表-list
    • 1.3 集合-set
    • 1.4 键值对-hash
    • 1.5 有序集合-zset
  • 2、Redis整合
    • 2.1 spring-boot-starter-data-redis 依赖
    • 2.2 redis配置
    • 2.3 SpringBoot框架自动配置的redisTemplate
      • 2.3.1 清空数据库
      • 2.3.2 添加数据
      • 2.3.3 获取数据
      • 2.3.4 修改值 (出现错误)
    • 2.4 自定义redisTemplate
      • 2.4.1 fastjson 依赖
      • 2.4.2 自定义redisTemplate 配置类
      • 2.4.3 使用自定义redisTemplate 重新操作数据
    • 2.5 自定义redisUtils工具类
      • 2.5.1 自定义redisUtils工具类
      • 2.5.2 使用自定义redisTemplate和redisUtils工具类
      • 2.5.3 程序中如何存放对象到 redis

1、五大基本数据类型和操作

1.1 字符串-string

命令 说明
set key value 如果key还没有,那就可以添加,如果key已经存在了,那会覆盖原有key的值
get key 如果key还没有,获取为(nil),代表key没有被使用,如果key存在,可以获取对应key的值
exists key 判断某个key是否存在,返回Integer值1 代表存在,如果 exists car2 则返回0,不存在
move key db 将当前数据库存在的键值移动到其它数据库,其中db是数据库的序号
expire key 秒钟 为已经存在的key设置过期时间,注意过期之后,从内存中去掉了,是get不到的
ttl key 查看还有多少秒过期,-1表示永不过期,-2表示已过期
type key 命令用于返回 key 所储存的值的类型
del key 根据key值删除
append key value 根据key将其值进行字符串拼接
strlen key 根据key获取其值的字符串长度,字节数
incr key 对key对应数值进行加一操作,对应的字符串值必须是数值
decr key 对key对应数值进行减一操作
incrby key 数值 对key对应数值按照指定的值进行递增
decrby key 数值 对key对应数值按照指定的值进行递减
getrange key 起始位置 结束位置 获取指定区间内的值,类似between。。。and的关系,起始位置为0,结束位置为-1 就是返回所有
setrange key 起始位置 具体值 设置指定区间内的值,具体值会从起始位置开始覆盖
setex key 过期秒值 真实值 设置带过期时间的key,动态设置。
setnx key value 只有在 key 不存在时,才会设置 key 的值,如果已经存在了,不覆盖,设置不了;
setnx key value 如果返回0 代表没有设置成功,key对应值已经存在,如果返回1代表设置成功;这个就是redis的分布式锁命令,很重要;
mset key1 val1 key2 val2 .... 同时设置一个或多个 key-value 对
mget key1 key2 key3 .... 获取所有(一个或多个)给定 key 的值。
msetnx key1 val1 key2 val2 ..... 同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在

1.2 列表-list

list操作起来类似于栈;

命令 说明
lpush key val1 val2 val3 .... 从左侧开始存放元素,先进后出
lrange key 起始位置 结束位置 从左侧开始,指定范围获取元素,-1代表所有
rpush key val1 val2 val3 .... 从右侧开始存放元素,先进先出
lpop key 从左侧一次取出一个元素
rpop key 从右侧一次取出一个元素
lindex key index 按照索引下标获得元素(从左到右,左下标从0开始,如果是-1代表最后一个,-2代表倒数第二个)
llen key 获取集合元素个数
lrem key 个数 具体的值 从左往右删除指定个数等于具体值的元素,返回的值为实际删除的数量,个数0,表示删除全部给定的值
ltrim key 开始index 结束index 截取指定范围的值后再赋值给key
rpoplpush 源列表 目的列表 移除列表的最后一个元素,并将该元素添加到另一个列表并返回
lset key index value 将key集合中的指定下标位置值改为value
linsert key before/after 值1 值2 在list某个已有 值1 的前后再添加具体 值2

小结:

  • 它是一个字符串链表,left、right都可以插入添加;
  • 如果键不存在,创建新的链表;
  • 如果键已存在,新增内容;
  • 如果值全移除,对应的键也就消失了;
  • 链表的操作无论是头和尾效率都极高,但假如是对中间元素进行操作,效率就很惨淡了;

1.3 集合-set

命令 说明
sadd key val1 val2 ... 集合set中添加元素,如果有重复元素会自动去除
smembers key 查看集合中的元素
sismember key val 判断val是否在set集合中,如果在返回1 ,不在返回0
scard key 获取集合里面的元素个数
srem key value 删除集合中元素
srandmember key 某个整数 随机出几个数,如果超过最大数量就全部取出
srandmember key 某个整数 如果写的值是负数,比如-3 ,表示需要取出3个,但是可能会有重复值。
spop key 随机出栈
smove key1 key2 将key1里的某个值赋给key2
sdiff key1 key2 在第一个set里面而不在后面任何一个set里面的项
sinter key1 key2 在两个set中都有的值的交集返回
sunion key1 key2 在两个set中所有的值的集合返回,会自动排除重复

1.4 键值对-hash

K V模式不变,但V是一个键值对;

命令 说明
hset 父key 子key 子value 将父key,增加子键值对,类似属性
hget 父key 子key 获取父key,某个子key的值,获取属性值
hmset 父key 子key1 子val1 子key2 子val2 .... 批量添加属性
hmget 父key 子key1 子key... 批量获取属性
hgetall 父key 批量获取属性及值
hdel 父key 子key 删除子key属性及值
hlen 父key 返回父key中的子key个数,相当于java实体的属性个数
hexists 父key 子key 判断父key中是否包含某个子key,结果为1,代表存在
hkeys 父key 获取父key中所有的子key
hvals 父key 获取父key中的所有的子val
hincrby 父key 子key 值 给指定的子key值增加固定的值
hincrbyfloat 父key 子key 值 给有指定key的值增加小数
hsetnx 父key 子key 子val 如果子key存在则失败,如果不存在则赋值

1.5 有序集合-zset

在set基础上,加一个score值。之前set是k1 v1 v2 v3,现在zset是k1 score1 v1 score2 v2;

命令 说明
zadd key score1 val1 score2 val2 score3 val3 ... 有序集合添加带score值的元素
zscore key val 获取集合中某个值对应score值
zrange key 0 -1 [withscores] zrange zset1 0 -1 ,结果为所有的值,不带分数;如:zrange zset1 0 -1 ,结果为所有的值,不带分数
zrange zset1 0 -1 withscores 结果为所有的值和分数
zrangebyscore key 开始score 结束score 获取score值在开始score-结束score之间的元素
zrangebyscore zset1 10 40 获取score值在10-40之间的元素,包含10和40
zrangebyscore zset1 10 (40 不包含40值;( 的含义是不包含
zrangebyscore zset1 (10 (40 不包含10,40值
zrangebyscore zset1 10 50 limit 2 2 limit 结果的起始下标,获取的个数;limit 含义是限制获取的条数,相当于mysql的分页;
zrem key 某score下对应的value值 删除元素
zcard key 获取key对应的值的个数;注意score 和 value是一个整体
zcount key score区间 获取分值区间内元素个数
zrank key values值 获得下标值
zscore key 对应value值 获得value对应分数
zrevrank key value值 逆序获得对应逆序的下标值
zrevrange key 起始下标,结束下标 将之前顺序进行倒序
zrevrangebyscore key 结束score 开始score 根据score值输出元素
zincrby key 增加分值 value值 给对应的值增加score值

2、Redis整合

2.1 spring-boot-starter-data-redis 依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.2 redis配置

#端口号
server:
  port: 8096

# redis配置
spring:
  redis:
    host: 127.0.0.1 #如果是redis远程服务器,此处redis服务器ip地址
    port: 6379 #默认端口
#    database: 0 #指定redis数据库,默认是0
#    password:   # 密码有就写,没有就省略

2.3 SpringBoot框架自动配置的redisTemplate

2.3.1 清空数据库

//自动装配  SpringBoot框架自动配置的redisTemplate
@Autowired
private RedisTemplate<Object,Object> redisTemplate;

//基于SpringBoot框架自动配置的redisTemplate,操作redis缓存
//获取连接
RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
//清空数据库中的所有数据
log.info("清空数据库中的所有数据");
connection.flushDb();

2.3.2 添加数据

//程序中,添加数据据到redis
log.info("------ 基于SpringBoot框架自动配置的redisTemplate 添加数据 ------");
redisTemplate.opsForValue().set("kh96_class_name","KGC_KH96");
redisTemplate.opsForValue().set("student_num",19);

2.3.3 获取数据

//程序中,从redis获取数据
log.info("------ 基于SpringBoot框架自动配置的redisTemplate 获取数据 ------");
log.info("****** 根据 班级的key:{},获取班级名称:{} ******","kh96_class_name",redisTemplate.opsForValue().get("kh96_class_name"));
log.info("****** 根据 班级的key:{},获取班级人数:{} ******","student_num",redisTemplate.opsForValue().get("student_num"));

2.3.4 修改值 (出现错误)

//程序中,基于SpringBoot框架自动配置的redisTemplate,操作redis缓存,存在问题
//场景:对班级人数进行增减操作,比如将班级人数,增加10
log.info("------ 基于SpringBoot框架自动配置的redisTemplate 操作数据 ------");
redisTemplate.opsForValue().increment("student_num",10);
//直接报错,会报500异常: redis.clients.jedis.exceptions.JedisDataException: ERR value is not an integer or out of range
//原因,通过系统默认的 redisTemplate,存放key和value值时,会自动使用Object类的序列化和反序列化,导致redis中真实存放的数据不是原始值,而是序列化后的值

数据结果:

2.4 自定义redisTemplate

2.4.1 fastjson 依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.62</version>
</dependency>

2.4.2 自定义redisTemplate 配置类

//Redis自定义配置类,实现一个自定义序列化方式的 redisTemplate,提缓缓掉默认自动配置的 redisTemplate,实现String类型任意类型的value
@Configuration
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // 自定义redisTemplate的模板对象
        RedisTemplate<String, Object> template = new RedisTemplate<>();

        // 设置连接工厂
        template.setConnectionFactory(redisConnectionFactory);

        //由于要通过程序操作远程的redis数据库,必须支持序列化,才可以让程序中的数据,在网络中传输
        //定义String类型的序列化方式
        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // 定义fastjson序列化方式,可以序列化任何对象
        FastJsonRedisSerializer<Object> fastJsonRedisSerializer = new FastJsonRedisSerializer<>(Object.class);

        // 需改为新的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        template.setValueSerializer(fastJsonRedisSerializer);
        template.setHashKeySerializer(stringRedisSerializer);
        template.setHashValueSerializer(fastJsonRedisSerializer);

        // 初始化为新的模板
        template.afterPropertiesSet();

        return template;
    }

}

2.4.3 使用自定义redisTemplate 重新操作数据

//自动装配自定义 redisTemplate
@Autowired
private RedisTemplate<String,Object> redisTemplate;

//其他代码不变

操作结果:

2.5 自定义redisUtils工具类

2.5.1 自定义redisUtils工具类

--->RedisUtil 工具类

2.5.2 使用自定义redisTemplate和redisUtils工具类

@GetMapping("/testRedisUtils")
public String testSpringBootRedisUtils(){

    //基于自定义的redisTemplate 和 RedisUtils 工具类,操作redis缓存
    //程序中,添加数据据到redis
    log.info("------ 基于自定义的redisTemplate 和 RedisUtils 工具类 添加数据 ------");
    redisUtils.set("kh96_class_name_utils","KGC_KH96");
    redisUtils.set("student_num_utils",19);

    //程序中,从redis获取数据
    log.info("------ 基于自定义的redisTemplate 和 RedisUtils 工具类 获取数据 ------");
    log.info("****** 根据 班级的key:{},获取班级名称:{} ******","kh96_class_name_utils",redisUtils.get("kh96_class_name_utils"));
    log.info("****** 根据 班级的key:{},获取班级人数:{} ******","student_num_utils",redisUtils.get("student_num_utils"));

    //程序中,基于SpringBoot框架自动配置的redisTemplate,操作redis缓存
    //场景:对班级人数进行增减操作,比如姜班级人数,增加10
    log.info("------ 基于自定义的redisTemplate 和 RedisUtils 工具类 操作数据 ------");
    redisUtils.incr("student_num_utils",10);

    return "工具类 RedisUtils  操作 redis 成功!";

}

2.5.3 程序中如何存放对象到 redis

核心思想:一般都是姜对象转换为json字符串,存入redis,获取对象数据,就先获取json字符串,再转换为对应对象即可;

@GetMapping("/testRedisUtils")
public String testSpringBootRedisUtils(){

    //程序中如何存放对象到 redis
    //核心思想:一般都是姜对象转换为json字符串,存入redis,获取对象数据,就先获取json字符串,再转换为对应对象即可

    //模拟用户登录成功后,将用户信息存入redis中,方便后续从redis中获取用户信息
    User loginUser = User.builder().userId(1001).userName("KH96").userTel("135012030404").build();

    //直接将对象存入redis即可
    log.info("------ 基于自定义的redisTemplate 和 RedisUtils 工具类 存储对象 ------");
    //自动把实体,通过fastjson的序列化方式,转发为JSON字符串存储
    redisUtils.set(loginUser.getUserId().toString(),loginUser);

    //模拟获取登录用户信息,直接从redis获取存入的JSON字符串,转换为目标用户对象
    User realUser = JSON.parseObject(redisUtils.get(loginUser.getUserId().toString()).toString(),User.class);

    log.info("------ 基于自定义的redisTemplate 和 RedisUtils 工具类获取对象:{} ",realUser);

    return "工具类 RedisUtils  操作 redis 成功!";

}

数据结果:

到此这篇关于SpringBoot中的Redis 缓存的文章就介绍到这了,更多相关SpringBoot Redis 缓存内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • redis如何实现清空缓存

    目录 redis如何清空缓存 正文 redis缓存问题如何清空 我的是免安装版的redis redis如何清空缓存 如果你们的项目用到redis啦,虽然设置了过期时间,但有时候修改bug,仍然需要及时清空缓存,去读数据库的数据,所以这篇文章讲解如何在linux下清除redis的缓存. 正文 1.首先进到redis的安装目录,进到src目录下,找到redis-cli 2.首先用账号密码的方式进入到redis的服务端 ./redis-cli -h 127.0.0.1 -p 6379  -a 1234

  • redis缓存一致性延时双删代码实现方式

    目录 redis缓存一致性延时双删代码 1.自定义注解 2.刪除逻辑 redis缓存延迟双删问题 redis缓存一致性延时双删代码 不废话...如下 1.自定义注解 /** *@author caoyue *延时双删 **/ @Retention(RetentionPolicy.RUNTIME) @Documented @Target(ElementType.METHOD) public @interface ClearCache {     boolean open() default tru

  • Redis缓存的主要异常及解决方案实例

    目录 1 导读 2 异常类型 2.1 缓存雪崩 2.1.1 现象 2.1.2 异常原因 2.1.3 解决方案 2.2 缓存穿透 2.2.1 现象 2.2.2 异常原因 2.2.3 解决方案 2.3 缓存击穿 2.3.1 现象 2.3.2 异常原因 2.3.3 解决方案 3 总结 1 导读 Redis 是当前最流行的 NoSQL数据库.Redis主要用来做缓存使用,在提高数据查询效率.保护数据库等方面起到了关键性的作用,很大程度上提高系统的性能.当然在使用过程中,也会出现一些异常情景,导致Redi

  • redis缓存延时双删的原因分析

    缓存为啥是删除,而不是更新? 如果是更新,存在分布式事务问题,可能出现修改了缓存,数据库修改失败的情况.只是删除缓存的话,就算数据库修改失败,下次查询会直接取数据库的数据,也不会出现脏数据. 延时双删是什么? 就是在增删改某实体类的时候,要对该实体类的缓存进行清空,清空的位置在数据库操作方法的前后. 采用反证法 只先删  只后删 结论 从而得出 前删和后删都有问题.所以采用延时双删的策略 思考2:为啥是延时 依然是反证法.下图这情况是双删依然存在旧缓存的情况,延时是确保 修改数据库->清

  • Mysql和redis缓存不一致问题的解决方案

    目录 一.问题描述 二.解决方案 1.给缓存数据设置过期时间 2.缓存延时双删 3.删除缓存重试机制 4.读取biglog异步删除缓存 三.总结 一.问题描述 redis.mysql双写缓存不一致: 在更新缓存方面,对于更新完数据库,是更新缓存呢,还是删除缓存.又或者是先删除缓存,再更新数据库,其实大家存在很大的争议.于是博主战战兢兢,写了这篇文章. 二.解决方案 1.给缓存数据设置过期时间 先做一个说明,从理论上来说,给缓存设置过期时间,是保证最终一致性的解决方案.这种方案下,我们可以对存入缓

  • Django使用Redis进行缓存详细步骤

    目录 1.背景和意义 2.配置步骤如下 1,服务器端安装 redis 2,Redis 访问控制 3,安装django-redis和settings配置 4,测试缓存是否成功 1.背景和意义 服务器数据非经常更新.若每次都从硬盘读取一次,浪费服务器资源.拖慢响应速度.而且数据更新频率较高,服务器负担比较大.若保存到数据库,还需要额外建立一张对应的表存储数据.在Django中建立表通常做法是建立一个模型.看似简单,但是调试麻烦.开发时长久.为了进行服务器的加速,使用Redis进行缓存. 2.配置步骤

  • SpringBoot项目中使用redis缓存的方法步骤

    本文介绍了SpringBoot项目中使用redis缓存的方法步骤,分享给大家,具体如下: Spring Data Redis为我们封装了Redis客户端的各种操作,简化使用. - 当Redis当做数据库或者消息队列来操作时,我们一般使用RedisTemplate来操作 - 当Redis作为缓存使用时,我们可以将它作为Spring Cache的实现,直接通过注解使用 1.概述 在应用中有效的利用redis缓存可以很好的提升系统性能,特别是对于查询操作,可以有效的减少数据库压力. 具体的代码参照该

  • springboot中使用redis由浅入深解析

    正文 很多时候,我们会在springboot中配置redis,但是就那么几个配置就配好了,没办法知道为什么,这里就详细的讲解一下 这里假设已经成功创建了一个springboot项目. redis连接工厂类 第一步,需要加上springboot的redis jar包 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redi

  • springboot中使用redis的方法代码详解

    特别说明: 本文针对的是新版 spring boot 2.1.3,其 spring data 依赖为 spring-boot-starter-data-redis,且其默认连接池为 lettuce ​redis 作为一个高性能的内存数据库,如果不会用就太落伍了,之前在 node.js 中用过 redis,本篇记录如何将 redis 集成到 spring boot 中.提供 redis 操作类,和注解使用 redis 两种方式.主要内容如下: •docker 安装 redis •springboo

  • 在SpringBoot中添加Redis及配置方法

    在实际的开发中,会有这样的场景.有一个微服务需要提供一个查询的服务,但是需要查询的数据库表的数据量十分庞大,查询所需要的时间很长. 此时就可以考虑在项目中加入缓存. 引入依赖 在maven项目中引入如下依赖.并且需要在本地安装redis. <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifac

  • SpringBoot中使用redis做分布式锁的方法

    一.模拟问题 最近在公司遇到一个问题,挂号系统是做的集群,比如启动了两个相同的服务,病人挂号的时候可能会出现同号的情况,比如两个病人挂出来的号都是上午2号.这就出现了问题,由于是集群部署的,所以单纯在代码中的方法中加锁是不能解决这种情况的.下面我将模拟这种情况,用redis做分布式锁来解决这个问题. 1.新建挂号明细表 2.在idea上新建项目 下图是创建好的项目结构,上面那个parent项目是其他项目不用管它,和新建的没有关系 3.开始创建controller,service,dao(mapp

  • SpringBoot中使用Redis的完整实例

    一.在SpringBoot中使用Redis的一套军体拳 1.导包 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> <version>2.2.0.RELEASE</version> </dependency> 2.导入工具类 packag

  • 在ssm项目中使用redis缓存查询数据的方法

    在项目中常常需要后台程序的持久层查询数据库来获取数据,然后将数据交给服务层.控制层,最后才交给视图层.如果数据访问缓慢,就会影响程序的运行. 为了加快程序的运行,可以将数据放入缓存中,包括数据缓存和页面缓存. 所谓缓存,就是将程序或系统经常要调用的对象存在内存中,一遍其使用时可以快速调用,不必再去创建新的重复的实例.这样做可以减少系统开销,提高系统效率. 其中页面缓存主要是oscache,可以整页或者指定网页某一部分缓存,同时指定他的过期时间,这样在此时间段里面访问的数据都是一样的 . 数据缓存

  • javaWeb中使用Redis缓存实例解析

    直接进入主题: 一:serviceImpl定义: @Service public class JedisClientSingleService implements JedisClient { @Autowired private JedisPool jedisPool; @Override public String get(String key) { Jedis jedis = jedisPool.getResource(); String string = jedis.get(key);

  • 详解在Java程序中运用Redis缓存对象的方法

    这段时间一直有人问如何在Redis中缓存Java中的List 集合数据,其实很简单,常用的方式有两种: 1. 利用序列化,把对象序列化成二进制格式,Redis 提供了 相关API方法存储二进制,取数据时再反序列化回来,转换成对象. 2. 利用 Json与java对象之间可以相互转换的方式进行存值和取值. 正面针对这两种方法,特意写了一个工具类,来实现数据的存取功能. 1. 首页在Spring框架中配置 JedisPool 连接池对象,此对象可以创建 Redis的连接 Jedis对象.当然,必须导

  • java、spring、springboot中整合Redis的详细讲解

    java整合Redis 1.引入依赖或者导入jar包 <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> 2.代码实现 public class JedisTest { public static void main(String[]

随机推荐