Redis

zy123
2025-03-21 /  0 评论 /  0 点赞 /  0 阅读 /  3455 字
最近更新于 04-26

Redis

Redis基本定义

Redis是一个基于内存的key-value结构数据库。Redis 是互联网技术领域使用最为广泛的存储中间件

Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库,官方提供的数据是可以达到100000+的QPS(每秒内查询次数)。它存储的value类型比较丰富,也被称为结构化的NoSql数据库(非关系型)。

典型场景

  • 热点数据缓存(商品/资讯/秒杀)
  • 会话管理(Session)
  • 排行榜/计数器
  • 消息队列(Stream)

NoSQL数据库

  • 键值型(Redis)

  • 文档型(MongoDB)

  • 列存储(HBase)

  • 图数据库(Neo4j)

下载与使用

Redis安装包分为windows版和Linux版:

角色 作用 典型示例
Redis 服务端 数据存储的核心,负责接收/执行命令、管理内存、持久化数据等。需先启动服务端才能使用。 redis-server(默认监听 6379 端口)
Redis 客户端 连接服务端并发送命令(如 GET/SET),获取返回结果。可以是命令行工具或代码库。 redis-cli、Java 的 Jedis 库

windows下服务启动/停止:

启动:

redis-server.exe redis.windows.conf

image-20250421172130160

这种方式关闭命令行后Redis服务又停止了!

解决方法:安装为 Windows 服务

redis-server --service-install redis.windows.conf --service-name Redis
redis-server --service-start

停止:

ctrl+c

客户端连接:

直接运行 redis-cli.exe 时,它会尝试连接 本机(127.0.0.1)的 Redis 服务端,并使用默认端口 6379。 等价于手动指定参数:

redis-cli -h 127.0.0.1 -p 6379

指定连接:

redis-cli -h <IP> -p <端口> -a <密码>
redis-cli -h 192.168.1.100 -p 6379 -a yourpassword

退出连接:exit

修改Redis配置文件

设置Redis服务密码,修改redis.windows.conf(windows) redis.conf(linux)

requirepass 123456

修改redis服务端口

port 6379

Redis客户端图形工具

默认提供的客户端连接工具界面不太友好,可以使用Another Redis Desktop Manager.exe ,类似Navicat连mysql。

Redis数据类型

image-20221130190150749

Redis存储的是key-value结构的数据,其中key是字符串类型,value有5种常用的数据类型:

  • 字符串(string):普通字符串,Redis中最简单的数据类型
  • 哈希(hash):也叫散列,类似于Java中的HashMap结构。(套娃)
  • 列表(list):按照插入顺序排序,可以有重复元素,类似于Java中的LinkedList
  • 集合(set):无序集合,没有重复元素,类似于Java中的HashSet(求交集)
  • 有序集合(sorted set/zset):集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素(排行榜)

Redis常用命令

通用命令

Redis的通用命令是不分数据类型的,都可以使用的命令:

  • KEYS pattern 查找所有符合给定模式( pattern)的 key

    • pattern:匹配模式,支持通配符:

      • *:匹配任意多个字符(包括空字符)
      • ?:匹配单个字符
      • [abc]:匹配 abc 中的任意一个字符
      • [a-z]:匹配 az 之间的任意一个字符
    • KEYS user:*    #可以返回 形如  "user:1"    "user:2" 的 key
      
    • KEYS *         #查找所有key
      
  • EXISTS key 检查给定 key 是否存在

  • TYPE key 返回 key 所储存的值的类型

  • DEL key 该命令用于在 key 存在是删除 key

字符串

Redis 中字符串类型常用命令:

  • SET key value 设置指定key的值
  • GET key 获取指定key的值
  • SETEX key seconds value 设置指定key的值,并将 key 的过期时间设为 seconds 秒(验证码)
  • SETNX key value 只有在 key不存在时设置 key 的值

哈希操作

Redis hash 是一个string类型的 field 和 value 的映射表,hash特别适合用于存储对象,常用命令:

  • HSET key field value 将哈希表 key 中的字段 field 的值设为 value
  • HGET key field 获取存储在哈希表中指定字段的值
  • HDEL key field 删除存储在哈希表中的指定字段
  • HKEYS key 获取哈希表中所有字段
  • HVALS key 获取哈希表中所有值
image-20221130193121969

列表操作

Redis 列表是简单的字符串列表,按照插入顺序排序,常用命令:

  • LPUSH key value1 将一个值插入到列表头部

  • RPUSH key value1 [value2] 将一个或多个值插入到列表尾部

    • RPUSH mylist "world" "redis" "rpush" #多个值插入
      
  • LRANGE key start stop 获取列表指定范围内的元素(这里L代表List 不是Left)

    • LRANGE mylist 0 -1  #获取整个列表
      
  • LLEN key 获取列表长度

  • RPOP key 移除并获取列表最后一个元素

  • BRPOP key1 [key2 ] timeout 移出并获取列表的最后一个元素, 如果列表没有元素会阻塞列表直到等待超 时或发现可弹出元素为止

image-20221130193332666

集合操作

Redis set 是string类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据,常用命令:

  • SADD key member1 [member2] 向集合添加一个或多个成员

    # 添加单个成员
    SADD fruits "apple"
    
    # 添加多个成员(自动去重)
    SADD fruits "banana" "orange" "apple"  # "apple" 已存在,不会重复添加
    
  • SMEMBERS key 返回集合中的所有成员

  • SCARD key 获取集合的成员数(基数Cardinality)

  • SINTER key1 [key2] 返回给定所有集合的交集

  • SUNION key1 [key2] 返回所有给定集合的并集

  • SREM key member1 [member2] 移除集合中一个或多个成员

image-20221130193532735

有序集合

Redis有序集合是string类型元素的集合,且不允许有重复成员。每个元素都会关联一个double类型的分数。常用命令:

常用命令:

  • ZADD key score1 member1 [score2 member2] 向有序集合添加一个或多个成员(score代表分数)
  • ZRANGE key start stop [WITHSCORES] 通过索引区间返回有序集合中指定区间内的成员
  • ZINCRBY key increment member 有序集合中对指定成员的分数加上增量 increment
  • ZREM key member [member ...] 移除有序集合中的一个或多个成员
image-20221130193951036

Java中操作Redis

Spring Data Redis 是 Spring 的一部分,提供了在 Spring 应用中通过简单的配置就可以访问 Redis 服务,就如同我们使用JDBC操作MySQL数据库一样。

网址:https://spring.io/projects/spring-data-redis

环境搭建

进入到sky-server模块

1). 导入Spring Data Redis的maven坐标(已完成)

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

2). 配置Redis数据源

在application-dev.yml中添加

sky:
  redis:
    host: localhost
    port: 6379
    password: 123456
    database: 10

解释说明:

database:指定使用Redis的哪个数据库,Redis服务启动后默认有16个数据库,编号分别是从0到15。

可以通过修改Redis配置文件来指定数据库的数量。

在application.yml中添加读取application-dev.yml中的相关Redis配置

spring:
  profiles:
    active: dev
  redis:
    host: ${sky.redis.host}
    port: ${sky.redis.port}
    password: ${sky.redis.password}
    database: ${sky.redis.database}

3). 编写配置类,创建RedisTemplate对象

@Configuration
@Slf4j
public class RedisConfiguration {
    @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;
    }
}

解释说明:

当前配置类不是必须的,因为 Spring Boot 框架会自动装配 RedisTemplate 对象,但是默认的key序列化器为

JdkSerializationRedisSerializer,存到 Redis 里会是二进制格式,这里把 key 的序列化器指定为 StringRedisSerializer,就会把所有的 key 都以 UTF‑8 字符串形式写入 Redis,方便观测和调试

功能测试

通过RedisTemplate对象操作Redis,注意要Another Redis Desktop中刷新一下数据库,才能看到数据。

字符串测试

@DataRedisTest
@Import(com.sky.config.RedisConfiguration.class)
public class SpringDataRedisTest {
    @Autowired
    private RedisTemplate redisTemplate;
    @Test
    public void testRedisTemplate(){
        System.out.println(redisTemplate);
    }
    @Test
    public void testString(){
        // SET city "北京"
        redisTemplate.opsForValue().set("city", "北京");

        // GET city
        String city = (String) redisTemplate.opsForValue().get("city");
        System.out.println(city);

        // SETEX code 180 "1234"    (3 分钟 = 180 秒)
        redisTemplate.opsForValue().set("code", "1234", 3, TimeUnit.MINUTES);

        // SETNX lock "1"
        redisTemplate.opsForValue().setIfAbsent("lock", "1");

        // (由于上一步 lock 已存在,这里相当于不执行)
        // SETNX lock "2"
        redisTemplate.opsForValue().setIfAbsent("lock", "2");
    }
}

对于非String类型:

写入时序列化

  • 调用 opsForValue().set(key, value) 时,value(比如 List<DishVO>)会先走一遍 ValueSerializer
  • 默认是 JdkSerializationRedisSerializer,它用 Java 的 ObjectOutputStream 把整个对象图打包成一个 byte[]。
  • 这个 byte[] 直接就存成了 Redis 的 String 值。

读取时反序列化

  • 调用 opsForValue().get(key) 时,RedisTemplate 拿回那段 byte[],再用同一个 JDK 序列化器(ObjectInputStream)把它变回 List<DishVO>

哈希测试

@Test
public void testHash(){
    HashOperations hashOperations = redisTemplate.opsForHash();

    // HSET 100 "name" "tom"
    hashOperations.put("100", "name", "tom");

    // HSET 100 "age" "20"
    hashOperations.put("100", "age", "20");

    // HGET 100 "name"
    String name = (String) hashOperations.get("100", "name");
    System.out.println(name);

    // HKEYS 100
    Set keys = hashOperations.keys("100");
    System.out.println(keys);

    // HVALS 100
    List values = hashOperations.values("100");
    System.out.println(values);

    // HDEL 100 "age"
    hashOperations.delete("100", "age");
}

get获得的是Object类型,keys获得的是set类型,values获得的是List

3). 操作列表类型数据

@Test
public void testList(){
    ListOperations listOperations = redisTemplate.opsForList();

    // LPUSH mylist "a" "b" "c"
    listOperations.leftPushAll("mylist", "a", "b", "c");

    // LPUSH mylist "d"
    listOperations.leftPush("mylist", "d");

    // LRANGE mylist 0 -1
    List mylist = listOperations.range("mylist", 0, -1);
    System.out.println(mylist);

    // RPOP mylist
    listOperations.rightPop("mylist");

    // LLEN mylist
    Long size = listOperations.size("mylist");
    System.out.println(size);
}

4). 操作集合类型数据

@Test
public void testSet(){
    SetOperations setOperations = redisTemplate.opsForSet();

    // SADD set1 "a" "b" "c" "d"
    setOperations.add("set1", "a", "b", "c", "d");

    // SADD set2 "a" "b" "x" "y"
    setOperations.add("set2", "a", "b", "x", "y");

    // SMEMBERS set1
    Set members = setOperations.members("set1");
    System.out.println(members);

    // SCARD set1
    Long size = setOperations.size("set1");
    System.out.println(size);

    // SINTER set1 set2
    Set intersect = setOperations.intersect("set1", "set2");
    System.out.println(intersect);

    // SUNION set1 set2
    Set union = setOperations.union("set1", "set2");
    System.out.println(union);

    // SREM set1 "a" "b"
    setOperations.remove("set1", "a", "b");
}

5). 操作有序集合类型数据

@Test
public void testZset(){
    ZSetOperations zSetOperations = redisTemplate.opsForZSet();

    // ZADD zset1 10 "a"
    zSetOperations.add("zset1", "a", 10);

    // ZADD zset1 12 "b"
    zSetOperations.add("zset1", "b", 12);

    // ZADD zset1 9 "c"
    zSetOperations.add("zset1", "c", 9);

    // ZRANGE zset1 0 -1
    Set zset1 = zSetOperations.range("zset1", 0, -1);
    System.out.println(zset1);

    // ZINCRBY zset1 10 "c"
    zSetOperations.incrementScore("zset1", "c", 10);

    // ZREM zset1 "a" "b"
    zSetOperations.remove("zset1", "a", "b");
}

6). 通用命令操作

  • * 匹配零个或多个字符。
  • ? 匹配任何单个字符。
  • [abc] 匹配方括号内的任一字符(本例中为 'a'、'b' 或 'c')。
  • [^abc][!abc] 匹配任何不在方括号中的单个字符。
@Test
public void testCommon(){
    // KEYS *
    Set keys = redisTemplate.keys("*");
    System.out.println(keys);

    // EXISTS name
    Boolean existsName = redisTemplate.hasKey("name");
    System.out.println("name exists? " + existsName);

    // EXISTS set1
    Boolean existsSet1 = redisTemplate.hasKey("set1");
    System.out.println("set1 exists? " + existsSet1);

    for (Object key : keys) {
        // TYPE <key>
        DataType type = redisTemplate.type(key);
        System.out.println(key + " -> " + type.name());
    }

    // DEL mylist
    redisTemplate.delete("mylist");
}
© 版权声明
THE END
喜欢就支持一下吧
点赞 0 分享 收藏
评论 抢沙发
取消