Java后端面试题攻略查漏补缺(五)

Java后端面试题攻略查漏补缺(五),第1张

1 Redis有哪些过期键删除策略? 1)定时删除

​ 创建一个定时器,到时间立即执行删除 *** 作

优点:对内存是友好的,保证过期键会尽可能快的被删除,并释放过期键所占用的内存

缺点:对cpu时间是最不友好的,过期键比较多的情况下,删除键会占用想当一部分的cpu时间,无疑会对服务器的响应时间和吞吐量造成影响

2)惰性删除

​ 键过期不管,每次获取键时检查是否过期,过期就删除(对cpu友好,但是只有在使用的时候才可能删除,对内存不友好)

优点:对cpu时间来说是最友好的,可以保证过期键的删除 *** 作只会在非做不可的情况下进行,并且删除目标仅限于当前处理的键。

缺点:对内存最不友好,如果一个键已经过期,而这个键又仍在然保留在数据库中,只要过期键不被删除,占用的内存就不会被释放。

3)定期删除

​ 每隔一段时间执行一次删除过期键的 *** 作,通过限制删除 *** 作执行时长和频率来减少删除 *** 作对cpu时间的影响,是对定时删除策略和惰性删除策略的整合和折中。

2 Redis缓存是如何回收?

当Redis占用内存超出最大限制 (maxmemory) 时,可采用如下策略 (maxmemory-policy) ,让Redis淘汰一些数据,以腾出空间继续提供读写服务 :

  • noeviction: 对可能导致增大内存的命令返回错误 (大多数写命令,DEL除外) ;
  • volatile-ttl: 在设置了过期时间的key中,选择剩余寿命 (TTL) 最短的key,将其淘汰;
  • volatile-lru: 在设置了过期时间的key中,选择最少使用的key (RU) ,将其淘汰;
  • volatile-random: 在设置了过期时间的key中,随机选择一些key,将其淘汰;
  • allkeys-1Lru: 在所有的key中,选择最少使用的key (LRU) ,将其淘汰;
  • allkeys-random: 在所有的key中,随机选择一些key,将其淘汰;
3 Redis的集群方案有哪些?

Redis支持三种集群方案:①主从复制模式 ②Sentinel(哨兵)模式 ③Cluster模式

1)主从复制模式

主从复制模式中包含一个主数据库实例(master)与一个或多个从数据库实例(slave)

工作机制:

  1. slave启动后,向master发送SYNC命令,master接收到SYNC命令后通过bgsave保存快照(RDB持久化),并使用缓冲区记录保存快照这段时间内执行的写命令
  2. master将保存的快照文件发送给slave,并继续记录执行的写命令
  3. slave接收到快照文件后,加载快照文件,载入数据
  4. master快照发送完后开始向slave发送缓冲区的写命令,slave接收命令并执行,完成复制初始化
  5. 此后master每次执行一个写命令都会同步发送给slave,保持master与slave之间数据的一致性

优点;

  1. master能自动将数据同步到slave,可以进行读写分离,分担master的读压力
  2. master、slave之间的同步是以非阻塞的方式进行的,同步期间,客户端仍然可以提交查询或更新请求

缺点:

  1. 不具备自动容错与恢复功能,master或slave的宕机都可能导致客户端请求失败,需要等待机器重启或手动切换客户端IP才能恢复
  2. master宕机,如果宕机前数据没有同步完,则切换IP后会存在数据不一致的问题
  3. 难以支持在线扩容,Redis的容量受限于单机配置
2)Sentinel(哨兵)模式

哨兵模式基于主从复制模式,只是引入了哨兵来监控与自动处理故障。

哨兵顾名思义,就是来为Redis集群站哨的,一旦发现问题能做出相应的应对处理。其功能包括

  1. 监控master、slave是否正常运行
  2. 当master出现故障时,能自动将一个slave转换为master
  3. 多个哨兵可以监控同一个Redis,哨兵之间也会自动监控

优点:

  1. 哨兵模式基于主从复制模式,所以主从复制模式有的优点,哨兵模式也有
  2. 哨兵模式下,master挂掉可以自动进行切换,系统可用性更高

缺点:

  1. 同样也继承了主从模式难以在线扩容的缺点,Redis的容量受限于单机配置
  2. 需要额外的资源来启动sentinel进程,实现相对复杂一点,同时slave节点作为备份节点不提供服务
3)Cluster集群模式

Cluster模式实现了Redis的分布式存储,即每台节点存储不同的内容,来解决在线扩容的问题

Cluster采用无中心结构,有如下特点:

  1. 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽
  2. 节点的fail是通过集群中超过半数的节点检测失效时才生效
  3. 客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可

优点:

  1. 无中心架构,数据按照slot分布在多个节点。

  2. 集群中的每个节点都是平等的关系,每个节点都保存各自的数据和整个集群的状态。每个节点都和其他所有节点连接,而且这些连接保持活跃,这样就保证了我们只需要连接集群中的任意一个节点,就可以获取到其他节点的数据。

    1. 可线性扩展到1000多个节点,节点可动态添加或删除
  3. 能够实现自动故障转移,节点之间通过gossip协议交换状态信息,用投票机制完成slave到master的角色转换

缺点:

  1. 客户端实现复杂,驱动要求实现Smart Client,缓存slots mapping信息并及时更新,提高了开发难度。目前仅JedisCluster相对成熟,异常处理还不完善,比如常见的“max redirect exception”
  2. 节点会因为某些原因发生阻塞(阻塞时间大于 cluster-node-timeout)被判断下线,这种failover是没有必要的
  3. 数据通过异步复制,不保证数据的强一致性。
  4. slave充当“冷备”,不能缓解读压力。
  5. 批量 *** 作限制,目前只支持具有相同slot值的key执行批量 *** 作,对mset、mget、sunion等 *** 作支持不友好
  6. key事务 *** 作支持有线,只支持多key在同一节点的事务 *** 作,多key分布不同节点时无法使用事务功能
  7. 不支持多数据库空间,单机redis可以支持16个db,集群模式下只能使用一个,即db0
4 Redis事务是如何实现的?

Redis事务本质:一组命令的集合!一个事务中的所有命令都会被序列化,在事务执行的过程中,会按照顺序执行!

一次性、顺序性、排他性!执行一系列的命令。

Redis事务没有隔离级别的概念!

所有的命令在事务中,并没有直接被执行!只有发起执行命令EXEC的时候才会执行!

Redis的事务执行:

  1. 开启事务(MULTI)
  2. 命令入队(…)
  3. 执行事务(EXEC)/放弃事务(DISCARD)
5 Zookepeer中的watch监听机制

zookeeper的订阅发布也就是watch机制,是一个轻量级的设计。因为它采用了一种推拉结合的模式。一旦服务端感知主题变了,那么只会发送一个事件类型和节点信息给关注的客户端,而不会包括具体的变更内容,所以事件本身是轻量级的,这就是所谓的“推”部分。然后,收到变更通知的客户端需要自己去拉变更的数据,这就是“拉”部分。watche机制分为添加数据和监听节点。

6 Zookeeper的数据模型和节点类型有哪些? 1)数据模型

ZooKeeper的视图结构和标准的Unix文件系统类似,其中每个节点称为“数据节点”或ZNode,每个znode可以存储数据,还可以挂载子节点,因此可以称之为“树”。

在Zookeeper中,znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据 ; 且通过客户端可对znode进行增删改查的 *** 作,还可以注册watcher监控znode的变化。 其数据模型可用下图进行表示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lP4rqJtd-1651072091309)(/Users/lu/Documents/%E8%B5%84%E6%96%99/java%E5%AD%A6%E4%B9%A0/%E9%9D%A2%E8%AF%95/src=http%253A%252F%252Fpic.qcsdn.com%252Fimg%252F20190414%252F069882bba2ff0b7cacfd9860aefa5991.png&refer=http%253A%252F%252Fpic.qcsdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto.png)]

2)节点类型 ①持久(persistent)节点:

(1) session断开后,数据不会丢失
(2)可以创建子节点

②临时(ephemeral)节点

(1)session断开后,数据会丢失
(2)不可以创建子节点

③持久顺序(PERSISTENT_SEQUENTIAL)节点

(1)、(2)同持久节点

(3)创建顺序节点时会默认设置顺序标识,即znode名称后会附加一个值 — 顺序号 ,顺序号是一个单调递增的计数器,由父节点维护

④临时顺序(EPHEMERAL_SEQUENTIAL)节点

Zookeeper实现分布式锁的基础。

(1)、(2)同临时节点,(3)同持久顺序节点

7 缓存穿透、缓存击穿、缓存雪崩在实际中如何解决 1)缓存穿透

​ 当用户访问的数据, **既不在缓存中,也不在数据库中,**导致请求在访问缓存时,发现缓存缺失,再去访问数据库时,发现数据库中也没有要访问的数据,没办法构建缓存数据,来服务后续的请求。那么当有大量这样的请求到来时,数据库的压力骤增,这就是 缓存穿透的问题。

应对缓存穿透的方案,常见的方案有三种。

  • 第一种方案,非法请求的限制;
  • 第二种方案,缓存空值或者默认值;
  • 第三种方案,使用布隆过滤器快速判断数据是否存在,避免通过查询数据库来判断数据是否存在;
2)缓存击穿

如果缓存中的 某个热点数据过期了,此时大量的请求访问了该热点数据,就无法从缓存中读取,直接访问数据库,数据库很容易就被高并发的请求冲垮,这就是 缓存击穿的问题。

应对缓存击穿可以采取两种方案:

  1. 互斥锁方案,保证同一时间只有一个业务线程更新缓存,未能获取互斥锁的请求,要么等待锁释放后重新读取缓存,要么就返回空值或者默认值。
  2. 不给热点数据设置过期时间,由后台异步更新缓存,或者在热点数据准备要过期前,提前通知后台线程更新缓存以及重新设置过期时间。
3)缓存雪崩

当 **大量缓存数据在同一时间过期(失效)或者 Redis 故障宕机时,**如果此时有大量的用户请求,都无法在 Redis 中处理,于是全部请求都直接访问数据库,从而导致数据库的压力骤增,严重的会造成数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃,这就是 缓存雪崩的问题。

不同的诱因,应对的策略也会不同。

针对大量数据同时过期,应对方法有下面这几种:

  1. 均匀设置过期时间;
  2. 互斥锁;
  3. 双 key 策略;
  4. 后台更新缓存;

针对Redis 故障宕机,应对方法有下面这几种:

  1. 服务熔断或请求限流机制;
  2. 构建 Redis 缓存高可靠集群;
8 分布式锁在项目中有哪些应用场景?

分布式锁为了解决分布式场景下全局加锁的问题。在单体项目中可以使用synchronize完成对于不同线程之间的资源争抢问题。但是在分布式场景下,synchronize只能对其中一个项目进行资源控制,进程之间的资源增强仍然无法解距。换言之,可以将分布式锁理解为对于整个分布式系统的synchronize。通常使用独立与线程之外的工具控制资源,如redis及框架redisson。

所以使用分布式锁的场景一般需要满足以下情况:

  1. 系统是一个分布式系统,集群系统,java的锁已经锁不住。
  2. *** 作共享资源,比如库里唯一的用户数据。
  3. 同步访问,即多个进程同时 *** 作共享资源。
9 分布式锁有哪些实现方案 1)基于数据库(唯一索引)

基于数据库的分布式锁可以有两种实现方式:

①基于数据库表

​ 直接创建一张锁表,然后通过 *** 作该表中的数据来实现了。当我们要锁住某个方法或资源时,我们就在该表中增加一条记录,想要释放锁的时候就删除这条记录。

②基于数据库排他锁

在SQL语句后面增加for update**,**数据库会在执行过程中给数据库表增加排他锁

2)基于缓存(Redis,memcached,tair)

基于Redis的分布式锁也有两种实现方式:

①基于setnx、expire及del三个命令来实现

​ 通过redis setnx(set if not exist)方式,当缓存里key不存在时,才会去set,否则直接返回false。如果返回true则获取到锁,否则获取锁失败,为了防止死锁,我们再用expire命令对这个key设置一个超时时间来避免。非原子实现。执行完业务 *** 作之后,删除该锁。

②基于Redisson来实现

3)基于Zookeeper

​ 使用zookeeper的临时有序节点,每个线程获取锁就在zookeeper创建一个临时有序的节点,比如在/lock目录下。

​ 创建节点成功后,获取/lock目录下的所有临时节点,再判断当前线程创建的节点是否是所有的节点的序号最小的节点;如果当前线程创建的节点是所有节点序号最小的节点,则认为获取锁成功;如果当前线程创建的节点不是所有节点序号最小的节点,则对节点序号的前一个节点添加一个事件监听。删除节点的时候就是解锁了。

10 Redis做分布式锁死锁时有哪些情况,如何解决?
  1. 加锁,没有释放锁的情况:需要添加释放锁的 *** 作,比如delete key。
  2. 加锁后,程序还没执行释放锁,程序挂掉,需要使用key过期机制。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/760105.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-01
下一篇 2022-05-01

发表评论

登录后才能评论

评论列表(0条)

保存