【Redis系列笔记】Redis入门

本文涉及的产品
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 MongoDB,通用型 2核4GB
简介: 本文介绍了Redis常用命令,以及SpringBoot集成Spring Data Redis和Spring Cache。Spring Data Redis 提供了对 Redis 的操作方法,而 Spring Cache 则提供了基于注解的缓存功能,可以方便地将方法的返回值缓存到 Redis 中,以提高性能和减少对数据源的访问次数。这样的集成可以帮助开发者更便捷地利用 Redis 来管理应用程序的数据和缓存。

1. 数据类型及常用命令

  • 字符串(string):普通字符串,Redis中最简单的数据类型
  • 哈希(hash):也叫散列,类似于Java中的HashMap结构,类似于对象
  • 列表(list):按照插入顺序排序,可以有重复元素,类似于Java中的LinkedList
  • 集合(set):无序集合,没有重复元素,类似于Java中的HashSet
  • 有序集合( zset):集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素
SET key value 
设置指定key的值
GET key    
获取指定key的值
SETEX key seconds value
设置指定key的值,并将 key 的过期时间设为 seconds 秒
SETNX key value 
只有在 key不存在时设置 key 的值
========================================================= 
HSET key field value  
将哈希表 key 中的字段 field 的值设为 value
HGET key field 
获取存储在哈希表中指定字段的值
HDEL key field  
删除存储在哈希表中的指定字段
HKEYS key  
获取哈希表中所有字段
HVALS key 
获取哈希表中所有值
========================================================= 
LPUSH key value1 [value2]
将一个或多个值插入到列表头部
LRANGE key start stop    
获取列表指定范围内的元素
RPOP key
移除并获取列表最后一个元素
LLEN key
获取列表长度
BRPOP key1 [key2 ] timeout
移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表
直到等待超时或发现可弹出元素为止
========================================================= 
SADD key member1 [member2]
向集合添加一个或多个成员
SMEMBERS key 
返回集合中的所有成员
SCARD key
获取集合的成员数
SINTER key1 [key2]
返回给定所有集合的交集
SUNION key1 [key2] 
返回所有给定集合的并集
SREM key member1 [member2] 
移除集合中一个或多个成员
========================================================= 
ZADD key score1 member1 [score2 member2] 
向有序集合添加一个或多个成员
ZRANGE key start stop [WITHSCORES] 
通过索引区间返回有序集合中指定区间内的成员
ZINCRBY key increment member  
有序集合中对指定成员的分数加上增量 increment
ZREM key member [member ...] 
移除有序集合中的一个或多个成员
========================================================= 
KEYS pattern 
查找所有符合给定模式( pattern)的 key 
EXISTS key 
检查给定 key 是否存在
TYPE key
返回 key 所储存的值的类型
DEL key  
该命令用于在 key 存在是删除 key

2. Spring Data Redis

2.1. 概述

前面我们讲解了Redis的常用命令,这些命令是我们操作Redis的基础,那么我们在java程序中应该如何操作Redis呢?这就需要使用Redis的Java客户端,就如同我们使用JDBC操作MySQL数据库一样。

Redis 的 Java 客户端很多,常用的几种:

  • Jedis
  • Lettuce
  • Spring Data Redis

Spring 对 Redis 客户端进行了整合,提供了 Spring Data Redis,在Spring Boot项目中还提供了对应的Starter,即 spring-boot-starter-data-redis。

Spring Data Redis 是 Spring 的一部分,提供了在 Spring 应用中通过简单的配置就可以访问 Redis 服务,对 Redis 底层开发包进行了高度封装。在 Spring 项目中,可以使用Spring Data Redis来简化 Redis 操作。

2.2. 操作步骤

  1. 导入Spring Data Redis 的maven坐标
<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-redis</artifactId>
        <version>2.7.3</version>
      </dependency>
  1. 配置Redis数据源
spring:
    redis:
      host: 192.168.200.128
      port: 6379
      password: redis
      database: 0
  1. 编写配置类,创建RedisTemplate对象
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
@Configuration
@Slf4j
public class RedisConfiguration {
    //提前步骤
    //添加依赖spring-boot-starter-data-redis
    //配置数据源yml,指定数据库位置,端口,密码
    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        log.info("开始创建redis模板对象");
        RedisTemplate redisTemplate = new RedisTemplate<>();
        //设置redis的连接工厂对象
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        //设置redis key的序列化器
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        return redisTemplate;
    }
}
  1. 通过RedisTemplate对象操作Redis
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.*;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@SpringBootTest
public class SpringRedisTest {
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    /**
     * redis 通用字符串命令
     */
    @Test
    public void testCommon(){
        /*
        KEYS pattern    查找所有符合给定模式( pattern)的 key
        EXISTS key    检查给定 key 是否存在
        TYPE key    返回 key 所储存的值的类型
        DEL key     该命令用于在 key 存在是删除 key
         */
        System.out.println(redisTemplate.keys("*"));
        System.out.println(redisTemplate.hasKey("age"));
        System.out.println(redisTemplate.type("age"));
        redisTemplate.rename("Student","Teacher");
        redisTemplate.delete("myset1");
    }
    // @Test
    // public void testOperation(){
    //     //获取字符串操作对象
    //     ValueOperations valueOperations = redisTemplate.opsForValue();
    //     HashOperations hashOperations = redisTemplate.opsForHash();
    //     ListOperations listOperations = redisTemplate.opsForList();
    //     SetOperations setOperations = redisTemplate.opsForSet();
    //     ZSetOperations zSetOperations = redisTemplate.opsForZSet();
    //
    // }
    /**
     * redis String字符串命令
     */
    @Test
    public void testString() {
        /*
        SET key value     设置指定key的值
        GET key     获取指定key的值
        SETEX key seconds value 设置指定key的值,并将 key 的过期时间设为 seconds 秒
        SETNX key value   只有在 key 不存在时设置 key 的值
         */
        ValueOperations valueOperations = redisTemplate.opsForValue();
        valueOperations.set("age", "刚满18岁");
        String age = (String) valueOperations.get("age");
        System.out.println(age);
        valueOperations.set("code", "120", 3, TimeUnit.SECONDS);
        valueOperations.setIfAbsent("lock", 1); 
        valueOperations.setIfAbsent("lock", 2);
    }
    /**
     * redis Hash字符串命令
     */
    @Test
    public void testHash() {
    /*
    HSET key field value  将哈希表 key 中的字段 field 的值设为 value
    HGET key field  获取存储在哈希表中指定字段的值
    HDEL key field    删除存储在哈希表中的指定字段
    HKEYS key     获取哈希表中所有字段
    HVALS key     获取哈希表中所有值
    */
        HashOperations hashOperations = redisTemplate.opsForHash();
        hashOperations.put("Student", "name", "xiaoming");
        hashOperations.put("Student","age","18");
        System.out.println(hashOperations.get("Student", "name"));
        System.out.println(hashOperations.get("Student", "age"));
        Set keys = hashOperations.keys("Student");
        List values = hashOperations.values("Student");
        System.out.println("keys = " + keys);
        System.out.println("values = " + values);
        hashOperations.delete("Student","age");
    }
    /**
     * redis List字符串命令
     */
    @Test
    public void testList(){
        /*
        LPUSH key value1 [value2]   将一个或多个值插入到列表头部
        LRANGE key start stop     获取列表指定范围内的元素
        RPOP key      移除并获取列表最后一个元素
        LLEN key      获取列表长度
         */
        ListOperations listOperations = redisTemplate.opsForList();
        listOperations.leftPushAll("list","a","b","c");
        listOperations.leftPush("list","e");
        System.out.println(listOperations.range("list", 0, -1));
        listOperations.leftPop("list");
        listOperations.rightPop("list");
        Long size = listOperations.size("list");
        System.out.println("size = " + size);
    }
    /**
     * redis Set字符串命令
     */
    @Test
    public void testSet(){
        /*
        SADD key member1 [member2]  向集合添加一个或多个成员
        SMEMBERS key    返回集合中的所有成员
        SCARD key       获取集合的成员数
        SINTER key1 [key2]    返回给定所有集合的交集
        SUNION key1 [key2]    返回所有给定集合的并集
        SREM key member1 [member2]  删除集合中一个或多个成员
         */
        SetOperations setOperations = redisTemplate.opsForSet();
        setOperations.add("myset1","x","y","z");
        setOperations.add("myset2","a","b","y");
        Set myset1 = setOperations.members("myset1");
        System.out.println("myset1 = " + myset1);
        Long size = setOperations.size("myset1");
        System.out.println("size = " + size);
        System.out.println(setOperations.intersect("myset1", "myset2"));
        System.out.println(setOperations.union("myset1", "myset2"));
        setOperations.remove("myset1","x");
    }
    /**
     * redis ZSet字符串命令
     */
    @Test
    public void testZSet(){
    /*
    ZADD key score1 member1 [score2 member2]  向有序集合添加一个或多个成员
    ZRANGE key start stop [WITHSCORES]    通过索引区间返回有序集合中指定区间内的成员
    ZINCRBY key increment member      有序集合中对指定成员的分数加上增量 increment
    ZREM key member [member ...]      移除有序集合中的一个或多个成员
     */
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        zSetOperations.add("zset1","a",10);
        zSetOperations.add("zset1","b",15);
        zSetOperations.add("zset1","c",11);
        zSetOperations.add("zset1","d",11);
        Set zset1 = zSetOperations.range("zset1", 0, -1);
        System.out.println("zset1 = " + zset1);
        zSetOperations.incrementScore("zset1","a",15);
        zSetOperations.remove("zset1","b");
    }
}

3. Spring Cache

3.1. 概述

在 Spring 3.1 中引入了多 Cache 的支持,在 spring-context 包中定义了org.springframework.cache.Cache 和 org.springframework.cache.CacheManager 两个接口来统一不同的缓存技术。Cache 接口包含缓存的常用操作:增加、删除、读取等。CacheManager 是 Spring 各种缓存的抽象接口。 Spring 支持的常用 CacheManager 如下:

CacheManager

描述

SimpleCacheManager

使用简单的 Collection 来存储缓存

ConcurrentMapCacheManager

使用 java.util.ConcurrentHashMap 来实现缓存

NoOpCacheManager

仅测试用,不会实际存储缓存

EhCacheCacheManger

使用EhCache作为缓存技术。EhCache 是一个纯 Java 的进程内缓存框架,特点快速、精干,是 Hibernate 中默认的 CacheProvider,也是 Java 领域应用最为广泛的缓存

JCacheCacheManager

支持JCache(JSR-107)标准的实现作为缓存技术

CaffeineCacheManager

使用 Caffeine 作为缓存技术。用于取代 Guava 缓存技术。

RedisCacheManager

使用Redis作为缓存技术

HazelcastCacheManager

使用Hazelcast作为缓存技术

CompositeCacheManager

用于组合 CacheManager,可以从多个 CacheManager 中轮询得到相应的缓存

Spring Cache 提供了 @Cacheable 、@CachePut 、@CacheEvict 、@Caching 等注解,在方法上使用。通过注解 Cache 可以实现类似事务一样、缓存逻辑透明的应用到我们的业务代码上,且只需要更少的代码。 核心思想:当我们调用一个方法时会把该方法的参数和返回结果最为一个键值对存放在缓存中,等下次利用同样的参数来调用该方法时将不会再执行,而是直接从缓存中获取结果进行返回。

注解

说明

@EnableCaching

开启缓存注解功能,通常加在启动类上

@Cacheable

在方法执行前先查询缓存中是否有数据,如果有数据,则直接返回缓存数据;

如果没有缓存数据,调用方法并将方法返回值放到缓存中

@CachePut

将方法的返回值放到缓存中

@CacheEvict

将一条或多条数据从缓存中删除

@Caching

缓存的结合体,可以组合以上注解在一个方法中使用,比如有新增,有删除

3.2. 操作步骤

  1. 依赖导入
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. 配置
spring:
  redis:
    host: 127.0.0.1
    port: 6379
    password: 123456
    database: 1
  1. 对应代码
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserService {
    @Autowired
    private UserMapper userMapper;
    /**
     * 将方法返回值放入缓存
     * @param user
     * @return
     */
    @CachePut(value = "userCache",key = "#user.id")
    public User insert(User user){
        userMapper.insert(user);
        return user;
    }
    /**
     *
     * @param id
     * @return
     */
    @Cacheable(cacheNames = "userCache",key = "#id")
    public User getById(Long id){
        //1.查询redis
        // String userStr = redisTemplate.opsForValue().get("redis:" + id);
        // if (userStr!=null){
        //     //命中
        //     User user = JSONObject.parseObject(userStr, User.class);
        //     return user;
        // }
        //未命中
        User user = userMapper.getById(id);
        if(user == null){
            throw new RuntimeException("用户不存在");
        }
        //同步数据到redis中
        //redisTemplate.opsForValue().set("redis:" + id, JSON.toJSONString(user));
        return user;
    }
    /**
     * 删除某个key对应的缓存数据
     * @param id
     */
    @CacheEvict(cacheNames = "userCache",key = "#id")
    public void deleteById(Long id){
        userMapper.deleteById(id);
    }
    /**
     * 删除所有数据,清理所有缓存
     */
    @CacheEvict(cacheNames = "userCache",allEntries = true)
    public void deleteAll(){
        userMapper.deleteAll();
    }
    /**
     * hashcode的特点是,只要参数相同,则生成后的hashcode值肯定相同
     * 如果返回结果为空,则不缓存unless="#result == null"或unless="#result.size()==0"
     * unless ="#result.size()==0" result是一个关键字,
     * @param userDto
     * @return
     */
    @Cacheable(value = "userCache",key = "#userDto.hashCode()",unless = "#result.size() == 0")
    public List<User> getList(UserDto userDto){
        List<User> list = userMapper.getList("%" + userDto.getName() + "%", userDto.getAge());
        return list;
    }
}
相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
1天前
|
NoSQL Java 关系型数据库
【Redis系列笔记】分布式锁
分布式锁:满足分布式系统或集群模式下多进程可见并且互斥的锁。 分布式锁的核心思想就是让大家都使用同一把锁,只要大家使用的是同一把锁,那么我们就能锁住线程,不让线程进行,让程序串行执行,这就是分布式锁的核心思路
126 2
|
1天前
|
NoSQL 关系型数据库 MySQL
redis 入门01
redis 入门01
14 0
|
1天前
|
存储 NoSQL Redis
【Redis系列笔记】Redis总结
Redis是一个基于内存的 key-value 结构数据库。 Redis 是互联网技术领域使用最为广泛的存储中间件。 Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。 它存储的value类型比较丰富,也被称为结构化的NoSql数据库。
68 0
|
1天前
|
存储 缓存 NoSQL
Redis笔记 | 青训营
Redis笔记 | 青训营
|
1天前
|
缓存 NoSQL Java
【Redis系列笔记】Redis事务
Redis事务的本质是一组命令的集合。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
64 3
|
1天前
|
缓存 NoSQL 算法
【Redis系列笔记】内存淘汰及过期删除
Redis是一个内存键值对数据库,所以对于内存的管理尤为重要。Redis内部对于内存的管理主要包含两个方向,过期删除策略和数据淘汰策略。内存淘汰策略指在Redis内存使用达到一定阈值的时候,执行某种策略释放内存空间,以便于接收新的数据。数据过期删除策略是指在数据的有效时间到期后,如何从内存中删除这些数据的规则。
44 0
|
1天前
|
存储 缓存 NoSQL
Redis入门到通关之Redis内存淘汰(内存过期)策略
Redis入门到通关之Redis内存淘汰(内存过期)策略
32 3
|
1天前
|
存储 NoSQL Linux
Redis入门到通关之多路复用详解
Redis入门到通关之多路复用详解
21 1
|
1天前
|
存储 NoSQL Linux
Redis入门到通关之Redis5种网络模型详解
Redis入门到通关之Redis5种网络模型详解
32 1
|
1天前
|
NoSQL Ubuntu 关系型数据库
Redis入门到通关之Redis网络模型-用户空间和内核态空间
Redis入门到通关之Redis网络模型-用户空间和内核态空间
22 1