2023/9/24总结

Redis

Redis 是一个基于内存的键值数据库

安装

Window下Redis的安装和部署详细图文教程(Redis的安装和可视化工具的使用)_redis安装_明金同学的博客-CSDN博客

2023/9/24总结_第1张图片

出现上面代表安装成功了

2023/9/24总结_第2张图片

redis 一共有 16 个库

2023/9/24总结_第3张图片

安装后 再安装图形化界面

图形界面十分方便去使用

redis数据结构介绍

redis 是 键值对的数据库  key 一般是 string 类型 但是 value 的类型 多种多样

String  类型

  • set  添加或者修改一个已经存在的String类型的键值对
  • get 获取到对应  key  的  value
  • mset  批量添加多个  String  类型的 键值对
  • mget  获取到所有  key  的 value
  • incr  让一个整型的  key  自增  1
  • incrby  让一个整型的  key  自增  并且指定 步长
  • incrbyfloat  让一个 浮点 类型 的数字自增并且指定步长
  • setnx  添加一个String 类型的 键值对  前提时 这个 key 不存在 否则不执行
  • setex  添加一个 String 类型的键值对  并且指定有效期

key 的结构  

redis 的 key 允许 有多个 单词 形成 层级结构  多个单词之间 用  :  隔开  

Hash 类型

类似于  java  中的 HashMap 结构  Hash  结构 可以将对象中的 每个  字段 独立存储  可以针对 单个字段做 CRUD

  • hset key field value 添加或者修改 hash 类型 key 的 field 的值
  • hset key field 获取一个hash类型key 的 field 的值
  • hmset 批量添加多个 hash 类型 key 的 field 的值
  • hmget 批量获取 多个 hash 类型 key 中的 所有 field 和 value
  • hgetall  获取一个hash类型的key中的所有的field 和 value
  • hkeys 获取一个hash 类型 key 中 所有的 field
  • hvals 获取一个hash 类型 的 key 中的 所有的 value
  • hincrby 让一个hash 类型 key 字段值 自增 并 指定步长
  • hsetnx 添加一个 hash 类型的 key 的 field 值 前提是这个 field 不存在 否则不执行

2023/9/24总结_第4张图片

2023/9/24总结_第5张图片

List  类型

redis 中 的 list 类型 与 java 中的 LinkedList 类似  可以看作 是一个 双向链表 结构 既可以支持 正向检索 也可以 支持 反向 检索

特征也与 LinkedList 类似 

  • 有序
  • 元素可以重复 
  • 插入和删除快
  • 查询速度一般
  • lpush  向 列表 左侧 插入 一个 或者 多个 元素
  • lpop 移除 并 返回 列表 左侧 第一个元素 没有则返回  nil
  • rpush  向 列表 右侧 插入 一个或者多个 元素
  • rpop 移除 并且 返回 列表 右侧 的 第一个元素
  • lrange  返回一段 下标 范围 内 的 所有 元素
  • blpop 和 brpop  与 lpop 和 rpop 类似 只不过 在 没有 元素 时 等待 指定时间 而不是直接 返回 nil

Set   类型

redis 的 set 结构 与 java 中的 HashSet 类似 可以看作 是一个 value 为 null 的 HashMap 

  • 无序
  • 元素 不可 重复
  • 查找快
  • 支持交集 并集 差集 等 功能
  • sadd 向 set 中 添加 一个多个元素
  • srem  移除 set 中的指定元素
  • scard 返回 set 中元素的个数
  • sismemery 判断 一个元素 是否存在 于 set 中
  • smemers 获取 set 中 所有 元素
  • sinter  求 集合 的 交集
  • sdiff  求 集合 的 差集
  • sunion 求 集合 的并集

2023/9/24总结_第6张图片

SortedSet 类型

redis 中的 SortedSet 是一个可排序 的 set 集合 与 java 中的 TreeSet 有些类似  但是底层 数据结构 却 差别 很大 SortedSet 中 每一个元素 都 带有 一个 score 属性 , 可以基于 score 属性 对元素 排序 。底层 的 实现 是一个 跳表 加 hash 表

  • 可排序
  • 元素 不重复
  • 查询速度快
  • zadd  添加 一个 或 多个元素 到 sortedset 中 如果已经存在 则 更新其 score 值
  • zrem  删除 sortedset 中的一个指定元素
  • zcore  获取 sortedset 中 指定 元素 的score值
  • zrank 获取 sortedset 中的元素个数
  • zcard 获取 sortedset 中元素个数
  • zcount 统计score 值在给定范围 内 所有 元素 的个数
  • zincrby 让sortedset 的指定元素自增  步长 为指定的 increment 值
  • zrange 按照score排序后  获取指定排名 范围内的元素
  • zrangebyscore 按照 score 排序后 获取指定 score 范围内 的 元素
  • zdiff zinter zunion 求差集  交集  并集

默认排名 都是 升序 如果还想要降序 在命令的后面 添加 rev 即可

2023/9/24总结_第7张图片

GEO 类型

BitMap  类型

HyperLog 类型

Redis 通用命令

  • keys  查看符合模板的所有key  不建议在生产环境使用
  • del  删除一个指定的key
  • exists  判断该 key 是否存在
  • expire  设置一个key的有效期  有效期到了后key会自动删除   单位是秒
  • TTL  查看一个key的剩余有效期  当TTL为 -1 时 说明该 数据 永久有效期  为 -2 时表示已经过期

2023/9/24总结_第8张图片

Jedis 的 使用

Jedis 是 redis 在java语言上的 客户端

Java guide | Redis

使用:

新建maven项目

依赖:


      redis.clients
      jedis
      4.3.1
    

测试代码:

package com.lxh;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import redis.clients.jedis.Jedis;

public class JedisTest {
    private Jedis jedis;

    @BeforeEach
    void setUp()
    {
        //建立连接
        jedis=new Jedis("127.0.0.1",6379);
//        如果你有设置密码 就要加下面这句话 我是并没有 设置密码的
//        jedis.auth("123456");
        jedis.select(0);
    }

    @Test
    void testString ()
    {
        String result=jedis.set("name","李泽言");
        System.out.println("result ="+result);

        String name = jedis.get("name");
        System.out.println("name="+name);
    }

    @AfterEach
    void tearDown()
    {
        if (jedis!=null)
        {
            jedis.close();
        }
    }
}

2023/9/24总结_第9张图片

Jedis 连接池

Jedis 本身 是 线程 不安全 的 ,并且 频繁 的 创建 和 销毁 会有性能损耗  因此 我们推荐大家 使用 Jedis 连接池 代替 Jedis 的 直连 方式

代码:

package com.lxh;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisClientConfig;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

public class JedisConnectionFactory {

    private static JedisPool jedisPool = new JedisPool();

    static {
        JedisPoolConfig jedisPoolConfig=new JedisPoolConfig();
        //设置最大连接数
        jedisPoolConfig.setMaxTotal(8);
        //设置最大空闲数
        jedisPoolConfig.setMaxIdle(8);
        //设置最小空间数
        jedisPoolConfig.setMinIdle(0);

        jedisPool = new JedisPool(jedisPoolConfig,"127.0.0.1",6379,1000);

    }

    public static Jedis getJedis(){
        return jedisPool.getResource();
    }
}

2023/9/24总结_第10张图片

运行结果:

2023/9/24总结_第11张图片

SpringDataRedis

SpringDataRedis 是 Spring 中数据 操作 的 模块 包含 各种 对 数据库 的 集成 其中对 Redis 的集成 模块 就叫做 SpringDataRedis 

Spring Data Redis

  •  提供了对不同 Redis 客户端的整合
  • 提供了 RedisTemplate 统一 API 来操作 Redis
  • 支持 Redis 的发布 订阅 模型
  • 支持 Redis 哨兵 和 Redis 集群
  • 支持 基于 Lettuce 的响应式编程
  • 支持 基于 JDK  JSON  字符串  Spring 对象 的数据 序列化 及 反序列化
  • 支持基于 Redis 的 JDKCollection 实现

SpringDataRedis 中提供了 对 RedisTamplate 工具类 其中封装了 对各种 Redis 的操作  并且将不同数据类型 的 操作 API 封装到了 不同的类中

2023/9/24总结_第12张图片

SpringDataRedis 使用步骤

新建一个 基于 maven 的 spring 的项目

引入 spring-boot-starter-data-redis 依赖



    4.0.0
    
        org.springframework.boot
        spring-boot-starter-parent
        3.1.4
         
    
    com.example
    redisData-demo
    0.0.1-SNAPSHOT
    redisData-demo
    redisData-demo
    
        17
    
    
        
            org.springframework.boot
            spring-boot-starter-data-redis
            3.0.4
        

        
            org.projectlombok
            lombok
            1.18.26
            true
        
        
            org.springframework.boot
            spring-boot-starter-test
            3.1.0
            test
        

        
            org.apache.commons
            commons-pool2
            2.11.1
        
    

    
        
            
                org.springframework.boot
                spring-boot-maven-plugin
                3.1.4
                
                    
                        
                            org.projectlombok
                            lombok
                        
                    
                
            
        
    


在 application.properties 下 写入这些

#这里是地址 localhost 对应 的 就是 127.0.0.1
spring.data.redis.host=localhost
#这里是端口号
spring.data.redis.port=6379
#如果你需要设置密码,就写这个 否则就不写
#spring.data.redis.password=12345
#当前使用的是哪一个 数据库 一共 是 下标 0 - 15
spring.data.redis.database=1
#是否使用线程池
spring.data.redis.lettuce.pool.enabled=true
#最大活动线程池个数
spring.data.redis.lettuce.pool.max-active=8
#最长等待时间 以毫秒 为单位
spring.data.redis.lettuce.pool.max-wait=2000
#这是最大 空闲 连接池 个数
spring.data.redis.lettuce.pool.max-idle=8

然后就是测试

package com.example.redisdatademo;

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.RedisTemplate;

@SpringBootTest
class RedisDataDemoApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    void contextLoads() {
    }

    @Test
    void testString()
    {
        //写入一条 String 数据
        redisTemplate.opsForValue().set("user","lizeyan");
        String user = (String) redisTemplate.opsForValue().get("user");
        System.out.println("user : "+user);
    }

}

运行 testString  能正确输出即可

SpringDataRedis  的 序列化方式

RedisTemplate 可以 接收任意 Object 作为 值 写入Redis 只不过 写入前会把Object序列化 为字节形式  默认是采用JDK序列化的 ,得到的结构就会变成 这样

2023/9/24总结_第13张图片

缺点  可读性差,内存占用大

我们可以重写方法 来修改 存入 redis 的数据状态

package com.example.redisdatademo;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
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.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.net.UnknownHostException;

@Configuration
public class redisDataConfig {

    @Bean
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) throws UnknownHostException
    {

        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);

        // 设置key和hashKey的序列化器为String类型
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());

        // 设置value和hashValue的序列化器为Jackson2JsonRedisSerializer
        Jackson2JsonRedisSerializer jsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jsonRedisSerializer.setObjectMapper(objectMapper);

        redisTemplate.setValueSerializer(jsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jsonRedisSerializer);

        redisTemplate.afterPropertiesSet();
        return redisTemplate;

//
//        //创建 Template
//        RedisTemplate redisTemplate=new RedisTemplate<>();
//        //设置连接工厂
//        redisTemplate.setConnectionFactory(redisConnectionFactory);
//        //设置序列化工具
//        GenericJackson2JsonRedisSerializer jsonRedisSerializer=new GenericJackson2JsonRedisSerializer();
//
//        //key 和 hashKey 采用 string 序列化
//        redisTemplate.setKeySerializer(RedisSerializer.string());
//        redisTemplate.setHashKeySerializer(RedisSerializer.string());
//
//        //value 和 hashValue 采用 string 序列化
//        redisTemplate.setValueSerializer(RedisSerializer.string());
//        redisTemplate.setHashValueSerializer(RedisSerializer.string());
//
//        return redisTemplate;
    }

}
 
  

要导入依赖

 
            com.fasterxml.jackson.core
            jackson-databind
            2.15.1
        

测试输出

2023/9/24总结_第14张图片

2023/9/24总结_第15张图片

如果按照上面这个方式 那么会需要额外的存储空间来存储 这个类的路径  为了节省 内存空间  我们并不会 使用 JSON 序列化 来处理 value 而是 使用 String 序列化 器 。要求 只能存储 String 类型的 key 和 value ,当需要 存储 java 对象 时 手动 完成对象 的序列化 和 反序列化。

Spring 默认提供了一个 StringRedisTemplate 类 它的 key 和 value 的序列化方式 默认就是String 方式 省去了 我们自定义 RedisTemplate 的过程

package com.example.redisdatademo;

import com.example.bean.User;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
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.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;

@SpringBootTest
class RedisDataDemoApplicationTests {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //JSON工具
    private static final ObjectMapper mapper=new ObjectMapper();

    @Test
    void contextLoads() {
    }

    @Test
    void testString()
    {
        //写入一条 String 数据
        redisTemplate.opsForValue().set("user","lizeyan");
        String user =(String) redisTemplate.opsForValue().get("user");
        System.out.println("user : "+user);
    }

    @Test
    void testObject()
    {
        redisTemplate.opsForValue().set("user:xm",new User("许墨",26));
        User newUser=(User) redisTemplate.opsForValue().get("user:xm");
        System.out.println(newUser);
    }

    @Test
    void testStringTemplate() throws JsonProcessingException {
        //准备对象
        User user=new User("helios",22);

        //手动序列化
        String json=mapper.writeValueAsString(user);
        //写入一条数据到 redis
        stringRedisTemplate.opsForValue().set("user:zql",json);

        //读取数据
        String val=stringRedisTemplate.opsForValue().get("user:zql");

        //反序列化
        User newUser=mapper.readValue(val,User.class);
        System.out.println("user : "+newUser);
    }

}

运行 testStringTemplate 就可以了 我们可以发现这个是没有类的路径的

2023/9/24总结_第16张图片

2023/9/24总结_第17张图片

 

你可能感兴趣的:(redis)