1.redis常见数据结构?
image-20211211112743856.png

字符串(string):普通字符串,常用

哈希(hash):适合存储对象

列表(list):按照插入顺序排序,可以有重复元素

集合(set):无序集合,没有重复元素

有序集合(sorted set / zset):集合中每个元素关联一个分数(score),根据分数升序排序,没有重复元素

2.redis在项目中的使用场景?

  1. rediskey 的数据结构是如何选型的
  2. rediskey的规范是如何设计的
  3. 具体业务是怎么样的
  4. 如何使用redis解决的业务

3.redis具体如何使用?

Spring Data Redis

1.依赖

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-redis</artifactId>
    <version>2.4.8</version>
</dependency>

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

2.配置application.yml

spring:
  #Redis相关配置
  redis:
    host: localhost
    port: 6379
    #password: 123456
    database: 0 #操作的是0号数据库
    jedis:
      #Redis连接池配置
      pool:
        max-active: 8 #最大连接数
        max-wait: 1ms #连接池最大阻塞等待时间
        max-idle: 4 #连接池中的最大空闲连接
        min-idle: 0 #连接池中的最小空闲连接

3.操作字符串类型数据

/**
 * 操作String类型数据
*/
@Test
public void testString(){
    //存值
    redisTemplate.opsForValue().set("city123","beijing");

    //取值
    String value = (String) redisTemplate.opsForValue().get("city123");
    System.out.println(value);

    //存值,同时设置过期时间
    redisTemplate.opsForValue().set("key1","value1",10l, TimeUnit.SECONDS);

    //存值,如果存在则不执行任何操作
    Boolean aBoolean = redisTemplate.opsForValue().setIfAbsent("city1234", "nanjing");
    System.out.println(aBoolean);
}

4.操作哈希类型数据

/**
 * 操作Hash类型数据
*/
@Test
public void testHash(){
    HashOperations hashOperations = redisTemplate.opsForHash();

    //存值
    hashOperations.put("002","name","xiaoming");
    hashOperations.put("002","age","20");
    hashOperations.put("002","address","bj");


    //取值
    String age = (String) hashOperations.get("002", "age");
    System.out.println(age);

    //获得hash结构中的所有字段
    Set keys = hashOperations.keys("002");
    for (Object key : keys) {
        System.out.println(key);
    }

    //获得hash结构中的所有值
    List values = hashOperations.values("002");
    for (Object value : values) {
        System.out.println(value);
    }
}

5.操作列表类型数据

/**
 * 操作List类型的数据
*/
@Test
public void testList(){
    ListOperations listOperations = redisTemplate.opsForList();

    //存值
    listOperations.leftPush("mylist","a");
    listOperations.leftPushAll("mylist","b","c","d");

    //取值
    List<String> mylist = listOperations.range("mylist", 0, -1);
    for (String value : mylist) {
        System.out.println(value);
    }

    //获得列表长度 llen
    Long size = listOperations.size("mylist");
    int lSize = size.intValue();
    for (int i = 0; i < lSize; i++) {
        //出队列
        String element = (String) listOperations.rightPop("mylist");
        System.out.println(element);
    }
}

5.操作集合类型数据

/**
 * 操作Set类型的数据
*/
@Test
public void testSet(){
    SetOperations setOperations = redisTemplate.opsForSet();

    //存值
    setOperations.add("myset","a","b","c","a");

    //取值
    Set<String> myset = setOperations.members("myset");
    for (String o : myset) {
        System.out.println(o);
    }

    //删除成员
    setOperations.remove("myset","a","b");

    //取值
    myset = setOperations.members("myset");
    for (String o : myset) {
        System.out.println(o);
    }

}

6.操作有序集合类型数据

/**
 * 操作ZSet类型的数据
*/
@Test
public void testZset(){
    ZSetOperations zSetOperations = redisTemplate.opsForZSet();

    //存值
    zSetOperations.add("myZset","a",10.0);
    zSetOperations.add("myZset","b",11.0);
    zSetOperations.add("myZset","c",12.0);
    zSetOperations.add("myZset","a",13.0);

    //取值
    Set<String> myZset = zSetOperations.range("myZset", 0, -1);
    for (String s : myZset) {
        System.out.println(s);
    }

    //修改分数
    zSetOperations.incrementScore("myZset","b",20.0);

    //取值
    myZset = zSetOperations.range("myZset", 0, -1);
    for (String s : myZset) {
        System.out.println(s);
    }

    //删除成员
    zSetOperations.remove("myZset","a","b");

    //取值
    myZset = zSetOperations.range("myZset", 0, -1);
    for (String s : myZset) {
        System.out.println(s);
    }
}

7.通用操作

/**
 * 通用操作,针对不同的数据类型都可以操作
*/
@Test
public void testCommon(){
    //获取Redis中所有的key
    Set<String> keys = redisTemplate.keys("*");
    for (String key : keys) {
        System.out.println(key);
    }

    //判断某个key是否存在
    Boolean itcast = redisTemplate.hasKey("itcast");
    System.out.println(itcast);

    //删除指定key
    redisTemplate.delete("myZset");

    //获取指定key对应的value的数据类型
    DataType dataType = redisTemplate.type("myset");
    System.out.println(dataType.name());

}

4.redis的事务机制的介绍?
Redis对于命令执行错误处理,有两种解决方式:

  • 语法错误(编译)
  • 执行错误(运行)

语法错误:执行命令的语法不正确。
此时整个事务队列中,存在一条正确指令,两条语法错误指令, 当执行exec后,会直接返回错误,正确的命令也不会执行。和我们正常理解的事务概念相同。

执行错误:命令在运行过程中出现错误。
通过上面事务执行可以看到,语法本身是没有问题的,所以运行之前redis无法发现错误,但是在执行时出现了错误,因此只会错误的命令不执行, 而正确的命令仍然能够正常执行。

5.redis的持久化机制?
1.RDB快照
RDB(Redis DataBase)是Redis默认存储方式。其基于快照思想,当符合一定条件(手动或自动触发)时,Redis会将这一刻的内存数据进行快照并保存在磁盘上,产生一个经过压缩的二进制文件,文件后缀名.rdb。
优点:

  • 基于二进制文件完成数据备份,占用空间少,便于文件传输。
  • 能够自定义规则,根据Redis繁忙状态进行数据备份。

缺点:

  • 无法保证数据完整性,会丢失最后一次快照后的所有数据。
  • bgsave执行每次执行都会阻塞Redis服务进程创建子线程,频繁执行影响系统吞吐率。

2.AOF
AOF(append only file)是Redis提供了另外一种持久化机制。与RDB记录数据不同,当开启AOF持久化后,Redis会将客户端发送的所有更改数据的命令,记录到磁盘中的AOF文件。 这样的话,当Redis重启后,通过读取AOF文件,按顺序获取到记录的数据修改命令,即可完成数据恢复。

模式 aof_buf写入到AOF是否阻塞 AOF文件写入磁盘是否阻塞 宕机重启时丢失的数据量 效率 安全
always 阻塞 阻塞 最多只丢失一个命令的数据
everysec 阻塞 不阻塞 不超过两秒的数据
no 阻塞 阻塞 操作系统最后一次对AOF写入磁盘的数据

6.RDB和AOF持久化的区别?

  1. RDB默认开启,AOF需手动开启。
  2. RDB性能优于AOF。
  3. AOF安全性优于RDB。
  4. AOF优先级高于RDB。
  5. RDB存储某个时刻的数据快照,AOF存储命令。
  6. RDB在配置触发状态会丢失最后一次快照以后更改的所有数据,AOF默认使用everysec,每秒保存一次,最多丢失两秒以内的数据。

7.redis高可用(集群策略)?

主从复制
* 读写分离:**主写从读**,提高服务器的读写负载能力

*  负载均衡:基于主从结构,配合读写分离,由slave分担master负载,并根据需求的变化,改变slave的数量,通过多个从节点分担数据读取负载,大大提高Redis服务器并发量与数据吞吐量

* 故障恢复:当master出现问题时,由slave提供服务,实现快速的故障恢复

* 数据冗余:实现数据热备份,是持久化之外的一种数据冗余方式

* 高可用基石:基于主从复制,构建哨兵模式与集群,实现Redis的高可用方案

哨兵模式
* 主从集群间可以实现自动切换,可用性更高
* 数据更大限度的防止丢失
* 解决哨兵的集群高可用问题,减少误判率

分片集群
 为了解决单机Redis容量有限的问题,将数据按一定的规则分配到多台机器,内存/QPS不受限于单机,提高并发量。

8.redis key的过期淘汰策略?

  • 定时删除
  • 惰性删除
  • 定期删除

9.redis 内存淘汰策略?
在Redis中默认提供了三类八种淘汰策略。image-20210302214348068.png

10.redis缓存穿透的问题?

11.redis缓存击穿的问题?

12.redis缓存雪崩的问题?

13.redis实现分布式锁的原理?