Spring注解方式整合Redis缓存及其五大数据类型常用命令

本文介绍了Redis的高速运行原理,并详细阐述了Redis的五大数据类型:String、List、Hash、Set和Zset,包括它们的应用场景和常用命令。接着,文章展示了如何在Spring中整合Redis缓存,包括配置、测试运行以及序列化问题。最后,提供了业务逻辑层的缓存注解使用和测试工具检验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

Redis

​ ​ redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化的Key-Value数据库。与传统数据库不同的是 redis 的数据是存在内存中的,所以读写速度非常快,因此 redis 被广泛应用于缓存方向。另外,redis 也经常用来做分布式锁。

​ redis安装后,在src和/usr/local/bin下有几个以redis开头的可执行文件,称为redis shell。

Redis执行命令说明
redis-server启动redis
redis-cliredis命令行工具
redis-benchmark基准测试工具
redis-check-aofAOF持久化文件检测工具和修复工具
redis-check-dumpRDB持久化文件检测工具和修复工具
redis-sentinel启动redis-sentinel

简述Redis的运行速度为何快?

  • 基于内存操作,手动持久化到硬盘
  • 高效数据结构,数据操作简单
  • 单线程,避开多线程上下文切换的操作
  • 多路I/O复用模型,非阻塞I/O
  • 底层模型不同,底层实现方式及与客户端之间通信的应用协议不一样
  • Redis直接自己构建了VM 机制 ,一般系统调用函数会浪费时间移动和请求

(一)五大数据类型

1、String-字符串

​ ​ String的数据结构为简单动态字符串。是可以修改的字符串,内部结构实现上类似于Java的ArrayList,最大value值为512M,可以包含任何数据,比如jpg图片(生成二进制)或者序列化的对象。

  • 应用场景:计数场景,用户的访问次数、热点文章的点赞转发数量。

  • 常用命令:set,get,strlen,exists,dect,incr,setex

    • set设置键值,使用get获取,使用getset命令获取当前键值并更新value值

      127.0.0.1:6379> set name zhangsan
      OK
      127.0.0.1:6379> get name
      "zhangsan"
      127.0.0.1:6379> getset name lisi
      "zhangsan"
      127.0.0.1:6379> get name
      "lisi"
      
    • strlen命令可获得当前键值对应value值的字节长度

      127.0.0.1:6379> strlen name
      (integer) 4
      
    • incr命令可将 key 中储存的数字值增一,incrby命令可将 key 中储存的数字增加任意数值

      127.0.0.1:6379> incr id
      (integer) 57
      127.0.0.1:6379> incrby id 10
      (integer) 67
      
    • decr命令可将 key 中储存的数字值减一,decrby命令可将 key 中储存的数字减少任意数值

      127.0.0.1:6379> decr id
      (integer) 66
      127.0.0.1:6379> decr by id
      (integer) 56
      
    • exists 命令用于检查给定 key 是否存在,存在为1,不存在为0.

      127.0.0.1:6379> exists name
      (integer) 1
      127.0.0.1:6379> exists na
      (integer) 0
      
    • setex为指定的 key 设置值及其过期时间,ttl命令查看当前时间

      127.0.0.1:6379> setex name 20 zhangsan
      OK
      127.0.0.1:6379> get name
      "zhangsan"
      127.0.0.1:6379> ttl name
      (integer) 11
      127.0.0.1:6379> ttl name
      (integer) 3
      127.0.0.1:6379> get name
      (nil)
      
    • setnx在指定的 key 不存在时,为 key 设置指定的值。

      127.0.0.1:6379> setnx name lisi
      (integer) 1
      127.0.0.1:6379> setnx name liwu
      (integer) 0
      
    • mset命令设置多个键值对,mget命令取多个键值。

      127.0.0.1:6379> mset name lisi sex nan
      OK
      127.0.0.1:6379> mget name sex
      1) "lisi"
      2) "nan"
      
    • append命令追加value值。

      127.0.0.1:6379> append name 123456789
      (integer) 13
      127.0.0.1:6379> get name
      "lisi123456789"
      

2、List-列表

​ ​ 链表是一种非常常见的数据结构,特点是易于数据元素的插入和删除并且且可以灵活调整链表长度,但是链表的随机访问困难。一个存储空间保存多个数据,且通过数据可以体现进入顺序。

  • 应用场景: 发布与订阅、消息队列、慢查询。

  • 常用命令:rpush,lpop,lpush,rpop,lrange、llen

    • rpush添加一个或多个值、lpush在头部添加一个或多个值。

      127.0.0.1:6379> lpush people lida wanger zhangsan
      (integer) 3
      127.0.0.1:6379> rpush people liqi wangba zhangjiu
      (integer) 6
      
    • lindex获得指定索引的元素,lrange获取指定范围的元素。

      127.0.0.1:6379> lindex people 2
      "lida"
      127.0.0.1:6379> lrange people 0 2
      1) "zhangsan"
      2) "wanger"
      3) "lida"
      
    • lpop移出并获取列表的第一个元素、rpop移除并获取列表最后一个元素。

      127.0.0.1:6379> lpop people
      "zhangsan"
      127.0.0.1:6379> rpop people
      "zhangjiu"
      127.0.0.1:6379>
      
    • llen获取当前长度

      127.0.0.1:6379> llen people
      (integer) 4
      

    • lrem移除列表元素

      127.0.0.1:6379> lrem people 1 wanger
      (integer) 1
      127.0.0.1:6379> lrange people 0 5
      1) "lida"
      2) "liqi"
      3) "wangba"
      
    • ltrim保留指定区间内的元素,移除其他所有元素

      127.0.0.1:6379> ltrim people 1 4
      OK
      127.0.0.1:6379> lrange people 0 10
      1) "wanger"
      2) "lisi"
      3) "zhangsan"
      4) "lida"
      
    • linsert在列表的元素前或者后插入元素

      127.0.0.1:6379> linsert people before lisi lier
      (integer) 5
      127.0.0.1:6379> lrange people 0 10
      1) "wanger"
      2) "lier"
      3) "lisi"
      4) "zhangsan"
      5) "lida"
      

3、Hash-哈希

​ ​ hash 类似于 JDK1.8 前的 HashMap,内部实现也差不多(数组 + 链表)。

​ ​ hash 是一个 string 类型的 field 和 value 的映射表,特别适合用于存储对象,后续操作的时候,你可以直接仅仅修改这个对象中的某个字段的值。

  • 应用场景:对象数据存储、电商网站购物车设计与实现。

  • 常用命令:hset,hmset,hexists,hget,hgetall,hkeys,hvals

    • hset将哈希表 key 中的字段 field 的值设为 value 。hget获取存储在哈希表中指定字段的值。

      127.0.0.1:6379> hset student name lisi
      (integer) 0
      127.0.0.1:6379> hget student name
      "lisi"
      
    • hmset将多个 field-value (域-值)对设置到哈希表 key 中、hmget获取所有给定字段的值。

      127.0.0.1:6379> hmset student name zhangsan age 24 sex nan
      OK
      127.0.0.1:6379> hmget student name age sex
      1) "zhangsan"
      2) "24"
      3) "nan"
      
    • hkeys获取所有哈希表中的字段、hvals获取哈希表中所有值、hgetall获取所有字段和值

      127.0.0.1:6379> hkeys student
      1) "name"
      2) "age"
      3) "sex"
      127.0.0.1:6379> hvals student
      1) "wangwu"
      2) "24"
      3) "nan"
      127.0.0.1:6379> hgetall student
      1) "name"
      2) "wangwu"
      3) "age"
      4) "24"
      5) "sex"
      6) "nan"
      
    • hexists查看哈希表 key 中,指定的字段是否存在。hlen 获取哈希表中字段的数量

      127.0.0.1:6379>  hexists student sex
      (integer) 1
      127.0.0.1:6379> hexists studeng gils
      (integer) 0
      127.0.0.1:6379> hlen student
      (integer) 3
      
    • hdel删除一个或多个哈希表字段

      127.0.0.1:6379> hdel student name
      (integer) 1
      127.0.0.1:6379> hgetall student
      1) "age"
      2) "24"
      3) "sex"
      4) "nan"
      

4、Set-无序集合

​ ​ set 类似于 Java 中的 HashSet 。
​ ​ Redis 中的 set 类型是一种无序集合,集合中的元素没有先后顺序。 set 提供了判断某个成员是否在一个 set 集合内的重要接口,这个也是 list 所不能提供的。可以基于 set 轻易实现交集、并集、差集的操作。

  • 应用场景:存放不重复的数据、获取多个数据源交集、并集和差集、共同喜爱、共同粉丝。

  • 常用命令:sadd,spop,smembers,sismember,scard,sinterstore,sunion

    • sadd向集合添加一个或多个成员、smembers返回集合中的所有成员、srem移除集合中一个或多个成员

      127.0.0.1:6379> smembers friends:1
      1) "1"
      2) "3"
      3) "5"
      4) "7"
      127.0.0.1:6379> smembers friends:2
      1) "1"
      2) "2"
      3) "5"
      4) "9"
      5) "10"
      
      127.0.0.1:6379> sadd friends:1  1 3 5 7 9
      (integer) 5
      127.0.0.1:6379> sadd friends:2  1 5 9 10 2
      (integer) 5
      127.0.0.1:6379> smembers friends:1
      1) "1"
      2) "3"
      3) "5"
      4) "7"
      5) "9"
      127.0.0.1:6379> srem friends:1 3 5
      (integer) 2
      127.0.0.1:6379> smembers friends:1
      1) "1"
      2) "7"
      3) "9"
      
    • sismeber判断元素是否是集合 key 的成员,scard获取集合的成员数

      127.0.0.1:6379> sismember friends:1 3
      (integer) 1
      127.0.0.1:6379> sismember friends:1 2
      (integer) 0
      127.0.0.1:6379> scard friends:2
      (integer) 5
      
    • srandmember返回集合中一个或多个随机数、spop移除并返回集合中的一个随机元素

      127.0.0.1:6379> srandmember friends:2
      "5"
      127.0.0.1:6379> srandmember friends:2
      "1"
      127.0.0.1:6379> spop friends:1
      "9"
      127.0.0.1:6379> smembers friends:1
      1) "1"
      2) "7"
      
    • sinter集合的交集、sunion集合的并集,sdiff集合的差集(以前集合为准)

      127.0.0.1:6379> sinter friends:1 friends:2
      1) "1"
      2) "5"
      127.0.0.1:6379> sunion friends:1 friends:2
      1) "1"
      2) "2"
      3) "3"
      4) "5"
      5) "7"
      6) "9"
      7) "10"
      127.0.0.1:6379> sdiff friends:1 friends:2
      1) "3"
      2) "7"
      

5、Zset-有序集合

​ ​ Zset 增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列,还可以通过 score 的范围来获取元素的列表。类似 Java 中 HashMap 和 TreeSet 的结合体。

​ ​ 根据评分( score )或者次序( position )来获取一个范围的元素。访问中间元素快。

  • 应用场景:数据根据某个权重排序、直播系统中的实时排行信息、直播间在线用户列表,礼物排行榜,弹幕消息、会员短期体验之过期失效。

  • 常用命令:zadd,zcard,zscore,zrange,zrevrange,zrem

    • zadd向有序集合添加一个或多个成员,或者更新已存在成员的分数。

      127.0.0.1:6379> zadd hot:note 55 1 44 2 33 3 22 4 11 5 1 6
      (integer) 6
      
    • zcard成员数、zcount指定区间分数的成员数、zscore成员的分数值

      127.0.0.1:6379> zcard hot:note
      (integer) 6
      127.0.0.1:6379> zcount hot:note 10 30
      (integer) 2
      127.0.0.1:6379> zscore hot:note 3
      "33"
      
    • zrange通过索引区间返回有序集合成指定区间内的成员,zrevrange分数从高到底

      127.0.0.1:6379> zrange hot:note 0 4
      1) "6"
      2) "5"
      3) "4"
      4) "3"
      5) "2"
      127.0.0.1:6379> zrevrange hot:note 0 4
      1) "1"
      2) "2"
      3) "3"
      4) "4"
      5) "5"
      
    • zrem移除有序集合中的一个或多个成员、

      127.0.0.1:6379> zrem hot:note 2
      (integer) 1
      

(二)整合spring缓存注解及属性

@Cacheable方法的返回值将被缓存,类上说明所有方法返回值存入缓存。
value / cacheNames指定缓存组件的名称
key / keyGenerator指定缓存数据所使用的的 key值
cacheManager / cacheResolver指定缓存管理器
condition判断属性,用来指定符合指定的条件下才可以缓存
unless指定的条件为 true 时,方法的返回值才不会被缓存。
sync指定是否使用异步模式,默认 false为同步模式。
@CacheEvict用来标注在需要清除缓存元素的方法或类上的
key指定缓存数据所使用的的 key值
value找到相同名称更新缓存数据,如没有相同,重新写入缓存
condition符合指定的条件下为true才可以缓存
allEntries将这个缓存中的数据全部删除
beforeInvocation缓存的清除是否在方法之前执行,默认代表在方法执行之后执行。
@CachePut确保添加注解的方法会执行,并将改变的数据写入缓存
key指定缓存数据所使用的的 key值
value找到相同名称更新缓存数据,如没有相同,重新写入缓存
condition符合指定的条件下为true才可以缓存

(三)快速使用

1、配置依赖

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

2、配置环境

		
	#配置redis
    spring.redis.host=localhost
    spring.redis.port=6379
    #连接超时5s  单位毫秒ms
    spring.redis.timeout=5000
		

3、测试运行

    
    @SpringBootTest
    public class RedisTest {
        @Resource
        private RedisTemplate<String, String> redisTemplate;

        @Test
        public void testRedis() {
            redisTemplate.opsForValue().set("test", "test2");
            System.out.println(redisTemplate.opsForValue().get("test"));
        }
    }
    

出现如下结果代表测试运行成功

在这里插入图片描述

4、Redis配置类(序列化)

默认序列化方式为JdkSerializationRedisSerializer, ISO-8859-1编码,在其他平台出现乱码问题;配置StringRedisSerializer序列化方式,其编码为 UTF-8,可以解决任意平台的乱码问题。

  • @EnableCaching代表注解驱动的缓存管理功能。

  • @Configuration将配置的组件添加到spring容器中。


@Configuration
@EnableCaching
public class RedisConfig {

    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {

        RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
        template.setConnectionFactory(factory);
        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        //["com.wanmait.demo.pojo.QuestionType",{"id":1,"title":"测试","questionCount":null,"sort":null,"enable":null,"info":null}]
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
        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;
    }
}

5、业务逻辑层

  • 在类上添加注解@CacheConfig代表此类下的所有方法有返回值时会存储进Redis缓存中。
  • cacheNamess属性代表此类下所有缓存数据均以此属性作为父名称。
  • @Cacheable带有属性时指定缓存数据所使用的的 key值,不带属性时不指定。
  • @CacheEvict清除缓存,allEntries=true属性代表全部清除。
  • @CachePut因为用list类型的存缓存,不推荐用@cachePut来更新缓存。
    
    @Service
    @CacheConfig(cacheNames = {" users "})
    public class UserService implements UserMapper {
        @Autowired
        private UserMapper userMapper;

        @Override
        @Cacheable
        public List<User> findAllUser() {
            return userMapper.findAllUser();
        }


        @Override
        @Cacheable(key = "#id")
        public User findUserById(Long id) {
            return userMapper.findUserById(id);
        }

        @Override
        public void insertUser(User user) {
            userMapper.insertUser(user);
        }

        @Override
        @CacheEvict(key = "#id",allEntries = true)
        public void deleteUser(Long id) {
            userMapper.deleteUser(id);
        }

        @Override
        //@CachePut(key = "#user.id", unless = "#result == null")
        public void updateUser(User user) {
            userMapper.updateUser(user);
        }

        @Override
        @Cacheable
        public List<User> findUser() {
            return userMapper.findUser();
        }

    }
    

6、测试工具检验

使用前端API测试工具发送请求,在Redis Desktop Manager可视化工具查看,如结果如下,说明缓存正常使用。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值