缓存JAVA进阶面试

Java面试题系列(十)——Redis

2021-05-25  本文已影响0人  嗨吖呀

1. 分布式数据库的CAP原理

2. BASE

3. Redis

  Remote dictionary server(远程字典服务器)是一个高性能的(key/value)分布式内存数据库,基于内存运行,并支持持久化的NoSQL数据库。具有如下特点:

4. Redis五大数据类型及应用场景

5. Redis String的实现

  Redis虽然是用C语言写的,但却没有直接用C语言的字符串,而是自己实现了一套字符串。目的就是为了提升速度,提升性能。Redis构建了一个叫做简单动态字符串(Simple Dynamic String),简称SDS

struct sdshdr{    
    //  记录已使用长度    
    int len;    
    // 记录空闲未使用的长度    
    int free;    
    // 字符数组    
    char[] buf;    
};  

Redis的字符串也会遵守C语言的字符串的实现规则,即最后一个字符为空字符。然而这个空字符不会被计算在len里头。

6. Redis持久化

7. Redis的事务

8. LUA脚本

9. Redis内存淘汰策略

1)  volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
2)  volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
3)  volatile-random:从已设置过期时间的数据集中任意选择数据淘汰。
4)  volatile-lfu:从已设置过期时间的数据集挑选使用频率最低的数据淘汰。
5)  allkeys-lru:从数据集中挑选最近最少使用的数据淘汰
6)  allkeys-lfu:从数据集中挑选使用频率最低的数据淘汰。
7)  allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
8)  no-enviction(驱逐):禁止驱逐数据,这也是默认策略。意思是当内存不足以容纳新入数据时,新写入操作就会报错,请求可以继续进行,线上任务也不能持续进行,采用no-enviction策略可以保证数据不被丢失。

10. 秒杀常见问题

11. Redis发布订阅

12. Redis主从复制

13. 哨兵模式

14. Java使用redis

    Transaction transaction = jedis.multi();
    transaction.set(“k2”,”v2”);
    transaction.set(“k3”,”v3”);
    transaction.exec();
public class TestTransaction {
  public boolean transMethod() {
     Jedis jedis = new Jedis("127.0.0.1", 6379);
     int balance;// 可用余额
     int debt;// 欠额
     int amtToSubtract = 10;// 实刷额度

     jedis.watch("balance");
     //jedis.set("balance","5");//此句不该出现。模拟其他程序已经修改了该条目
     balance = Integer.parseInt(jedis.get("balance"));
     if (balance < amtToSubtract) {
       jedis.unwatch();
       System.out.println("modify");
       return false;
     } else {
       System.out.println("***********transaction");
       Transaction transaction = jedis.multi();
       transaction.decrBy("balance", amtToSubtract);
       transaction.incrBy("debt", amtToSubtract);
       transaction.exec();

       balance = Integer.parseInt(jedis.get("balance"));
       debt = Integer.parseInt(jedis.get("debt"));

       System.out.println("*******" + balance);
       System.out.println("*******" + debt);
       return true;
     }
  }

  /**
   * 通俗点讲,watch命令就是标记一个键,如果标记了一个键, 在提交事务前如果该键被别人修改过,那事务就会失败,这种情况通常可以在程序中重新再尝试一次。
   * 首先标记了键balance,然后检查余额是否足够,不足就取消标记,并不做扣减; 足够的话,就启动事务进行更新操作,
   * 如果在此期间键balance被其它人修改, 那在提交事务(执行exec)时就会报错, 程序中通常可以捕获这类错误再重新执行一次,直到成功。
   */
  public static void main(String[] args) {
     TestTransaction test = new TestTransaction();
     boolean retValue = test.transMethod();
     System.out.println("main retValue-------: " + retValue);
  }
}
JedisPoolConfig poolConfig = new JedisPoolConfig( );
poolConfig.setMaxActive ( 1000);
poolconfig.setMaxIdle ( 32);
poolconfig. setMaxwait (100*1000);poolconfig.setTestOnBorrow(true);

jedisPool = new JedisPool(poolConfig, "127.0.0.1",6379);

-   maxActive:控制一个pool可分配多少个jedis实例,通过pool.getResource()来获取;如果赋值为-1,则表示不限制;如果pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted。
-   maxIdle:控制一个pool最多有多少个状态为idle(空闲)的jedis实例;
-   whenExhaustedAction:表示当pool中的jedis实例都被allocated完时,pool要采取的操作:默认有三种。
-   WHEN_EXHAUSTED_FAIL -->表示无jedis实例时,直接抛出NoSuchElementException;
-   WHEN_EXHAUSTED_BLOCK -->则表示阻塞住,或者达到maxWait时抛出JedisConnectionException;
-   WHEN_EXHAUSTED_GRoW -->则表示新建一个jedis实例,也就说设置的maxActive无用;
-   maxWait:表示当borrow一个jedis实例时,最大的等待时间,如果超过等待时间,则直接抛JedisConnectionException;
-   testOnBorrow:获得一个jedis实例的时候是否检查连接可用性(ping());如果为true,则得到的jedis实例均是可用的:

15. 解决session存储问题

16. 单线程+多路IO复用

  多路复用是指用一个线程来检查多个文件描述符(socket)的就绪状态,比如调用select、poll、epoll函数进行监视,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。得到就绪状态后进行真正的操作可以在同一个线程里执行,也可以启动线程执行(比如使用线程池)。
  多路I/O复用模型是利用 select、poll、epoll 可以同时监察多个流的 I/O 事件的能力,在空闲的时候,会把当前线程阻塞掉,当有一个或多个流有 I/O 事件时,就从阻塞态中唤醒,于是程序就会轮询一遍所有的流(epoll 是只轮询那些真正发出了事件的流),并且只依次顺序的处理就绪的流,这种做法就避免了大量的无用操作。这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。

17. Select、poll、epoll

18. REDIS缓存穿透,缓存击穿,缓存雪崩原因+解决方案

19. 布隆过滤器

  布隆过滤器由「初始值都为 0 的位图数组」和「 N 个哈希函数」两部分组成。当我们在写入数据库数据时,在布隆过滤器里做个标记,这样下次查询数据是否在数据库时,只需要查询布隆过滤器,如果查询到数据没有被标记,说明不在数据库中。
布隆过滤器会通过 3 个操作完成标记:

  在数据库写入数据 x 后,把数据 x 标记在布隆过滤器时,数据 x 会被 3 个哈希函数分别计算出 3 个哈希值,然后在对这 3 个哈希值对 8 取模,假设取模的结果为 1、4、6,然后把位图数组的第 1、4、6 位置的值设置为 1。当应用要查询数据 x 是否数据库时,通过布隆过滤器只要查到位图数组的第 1、4、6 位置的值是否全为 1,只要有一个为 0,就认为数据 x 不在数据库中。
  布隆过滤器由于是基于哈希函数实现查找的,高效查找的同时存在哈希冲突的可能性,比如数据 x 和数据 y 可能都落在第 1、4、6 位置,而事实上,可能数据库中并不存在数据 y,存在误判的情况。
  所以,查询布隆过滤器说数据存在,并不一定证明数据库中存在这个数据,但是查询到数据不存在,数据库中一定就不存在这个数据。

20. 为什么要用redis而不用map做缓存?

21. 如何保持缓存和数据库的一致性?

public void write(String key,Object data){
    redisUtils.del(key);
    db.update(data);
    Thread.Sleep(100);
    redisUtils.del(key);
}

22. Redis分布式锁的实现

23. Redis集群

  1. Redis部署模型
  1. Redis缓存预热
上一篇 下一篇

猜你喜欢

热点阅读