Java面试题11

1.redis 是什么?都有哪些使用场景?

        Redis(Remote Dictionary Server)是一个开源的内存数据存储系统,它支持键值对存 储,并提供了多种数据结构如字符串、哈希、列表、集合、有序集合等。Redis主要用于高速缓 存、会话存储、排行榜、实时消息发布订阅等场景。

Redis(Remote Dictionary Server)即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

Redis的主要使用场景包括会话缓存(Session Cache)、全页缓存(FPC)、排行榜/计数器、队列、发布/订阅等。例如,用Redis缓存会话相对于其他存储(如Memcached)而言,其优势在于Redis提供持久化服务

2.redis 有哪些功能?

Redis具有以下主要功能:

  • 数据持久化:支持将内存数据持久化到硬盘,确保数据不会丢失。
  • 分布式数据存储:支持分布式集群部署,实现数据的高可用和负载均衡。
  • 发布订阅:支持实时消息的发布和订阅。
  • 数据结构支持:提供多种数据结构,如字符串、哈希、列表、集合、有序集合等,方便存储 不同类型的数据。
  • 事务支持:支持基于MULTI、EXEC、WATCH等命令的事务操作。
  • 位图计算、地理位置计算等特定功能。
  • 内存缓存:将热点数据存储在内存中,加速读取速度。

Redis是一种内存数据库,它具有快速的数据访问和高效的数据存储,适合用作缓存的存储层。它支持多种数据结构,如字符串、哈希表、列表、集合、有序集合等。此外,Redis还具有持久化、发布/订阅、事务、排序等功能。

  1. 持久化:Redis可以将内存中的数据写入到硬盘中,在重新启动时加载这些数据,从而最大限度的降低缓存丢失带来的影响。
  2. 发布/订阅:Redis提供了发布/订阅功能,可以用于实现消息的传递和订阅。
  3. 事务:Redis支持事务处理,可以在一次操作中执行多个命令,并保证事务的原子性。
  4. 排序:Redis支持对列表、有序集合等数据进行排序操作。

3.redis 和 memcached 有什么区别?

        Redis和Memcached都是内存中的键值存储系统,但有一些区别:

  • 数据持久化:Redis支持数据的持久化,可以将数据保存到硬盘中,而Memcached不支持数 据持久化。
  • 数据安全:Redis支持数据的备份和恢复,支持主从复制和数据分片,保证数据安全性和高可 用性。
  • 单线程:Redis是单线程的,通过事件循环实现高效的并发处理,而Memcached是多线程 的。
  • 扩展性:Redis支持分布式集群部署,支持更多的扩展性和高可用性。
  • 数据结构:Redis支持更多的数据结构,如哈希、有序集合等,Memcached只支持简单的键 值对。

Redis和Memcached都是内存数据存储系统,但它们在功能和使用场景上存在一些区别。

  1. 数据结构:Redis支持更多的数据结构类型,如字符串、散列、列表、集合、有序集、位图、超级日志和空间索引,而Memcached只支持字符串和整数。
  2. 执行速度:Memcached的读写速度高于Redis。
  3. 复制:Redis支持主从复制,允许从属Redis服务器成为主服务器的精确副本,而Memcached不支持复制。
  4. 密钥长度:Redis的密钥长度最大为2GB,而Memcached的密钥长度最大为250字节。
  5. 线程:Redis是单线程的,而Memcached是多线程的。
  6. 数据持久化:Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,这是与Memcached相比一个最大的区别。
  7. 内存使用:Redis不仅仅将数据存放在内存中,还可以将一些很久没用到的数据交换到磁盘上,从而有效防止内存使用过多的问题。
  8. 过期策略:Memcache在set时就指定过期时间,例如set key1 0 0 8,即永不过期;而Redis可以通过expire设定过期时间。
  9. 分布式:Memcache可以设定集群,利用magent做一主多从;Redis也可以做一主多从。

4.redis 为什么是单线程的?

        Redis之所以采用单线程的方式,是因为它主要用于高速缓存和高速读取的场景。单线程可 以避免多线程之间的上下文切换开销,同时通过事件循环(Event Loop)机制实现高效的并发处 理。在典型的缓存场景下,CPU并不是瓶颈,而是内存和网络带宽。单线程可以更好地利用CPU缓 存,同时降低了线程同步和锁的开销。

Redis选择使用单线程模型的原因是为了简化设计和实现,并且由于它的特定工作负载和使用情况,单线程在许多情况下能够提供优越的性能。

首先,Redis是基于内存操作的,每个操作执行速度都非常快。在单线程模型下,不需要考虑多线程同步的问题,从而避免了线程切换和锁竞争导致的性能消耗。这使得Redis在处理大量并发请求时能够保持高效。

其次,Redis中的数据结构相对简单,对数据的操作也很快。单线程模型避免了多线程处理中可能出现的竞争和同步问题,进一步提高了性能。

此外,Redis还使用了多路复用IO技术,即非阻塞IO。这种技术可以处理多个网络连接产生的流,并且一个线程可以服务多条IO流。这使得Redis在处理大量并发连接时能够保持高效。

总之,Redis的单线程模型是其高性能的关键之一。然而,这并不意味着单线程模型在所有情况下都是最佳选择。在处理非常大的数据集或非常高的并发负载时,使用多线程模型可能会更合适。但是,对于大多数常见的用例,单线程模型已经足够高效并且更简单。

5.什么是缓存穿透?怎么解决?

        缓存穿透是指恶意请求访问缓存中不存在的数据,导致每次请求都需要访问数据库,增加了 数据库的负担。解决缓存穿透问题的方式有:

  • 空值缓存:如果数据库中不存在某个键的值,将其对应的缓存设置为空值,避免重复查询。
  • 预热缓存:系统启动时预先将热点数据加载到缓存中,减少冷启动时的穿透情况。
  • 布隆过滤器:在缓存层引入布隆过滤器,用于过滤掉不存在的请求,从而避免访问数据库。

缓存穿透是指在高并发场景下,如果某一个 key 被高并发访问,没有被命中,出于对容错性考虑,会尝试去从后端数据库中获取,从而导致了大量请求到达数据库,而当该 key 对应的数据库本身就是空的情况下,这就导致数据库中并发的去执行了很多不必要的查询操作,从而导致巨大冲击和压力。

缓存穿透的解决方案:

  1. 缓存空对象:对查询结果为空的对象也进行缓存,如果是集合,可以缓存一个空的集合(非 null ),如果是缓存单个对象,可以通过字段标识来区分。这样避免请求穿透到后端数据库。同时,也需要保证缓存数据的时效性。这种方式实现起来成本较低,比较适合命中不高,但可能被频繁更新的数据。
  2. 单独过滤处理:对所有可能对应数据为空的 key 进行统一的存放,并在请求前做拦截,这样避免请求穿透到后端数据库。这种方式实现起来相对复杂,比较适合命中不高,但是更新不频繁的数据。
  3. 布隆过滤器是一种概率型数据结构,可以用于在大数据量的集合中判定某元素是否存在。它的优点是空间效率和查询时间都远远超过一般的算法,缺点是有一定的误识别率和删除困难。为了减少冲突,可以多引入几个Hash,如果通过其中的一个Hash值得出某元素不在集合中,那么该元素肯定不在集合中。

6.redis 支持的数据类型有哪些?

        Redis支持多种数据类型,包括字符串(String)、哈希(Hash)、列表(List)、集合 (Set)、有序集合(Sorted Set)等。

        

Redis支持五种数据类型:string(字符串)、hash(哈希)、list(列表)、set(集合)及zset(有序集合)。

  1. string是最基本的数据类型,一个key对应一个value,且是二进制安全的,最大能存储512MB。
  2. hash是一个键值对集合,特别适合用于存储对象。
  3. list是简单的字符串列表,按照插入顺序排序。
  4. set是string类型元素的集合,且不允许重复的成员。
  5. zset和set一样也是string类型元素的集合,且不允许重复的成员,但是它是有序的,即每个元素都有一个分数,根据分数排序。

7.redis 支持的 Java 客户端都有哪些?

Redis支持多种Java客户端,常用的有Jedis、Lettuce、Redisson等。

Redis 支持的 Java 客户端包括 Jedis、Lettuce 和 Redisson。

  • Jedis:Jedis 是一款简单易用的 Redis 客户端,支持同步和异步操作,以及许多高级功能。
  • Lettuce:Lettuce 是一个高性能的 Redis 客户端,它支持同步和异步操作,并具有高级特性,如连接池和异步 API。
  • Redisson:Redisson 是一个高级的分布式协调 Redis 客户端,它支持许多分布式特性,如发布/订阅、锁和分布式集合等。

官方推荐使用的 Java 客户端是 Redisson。

8.jedis 和 redisson 有哪些区别?

        Jedis和Redisson都是Redis的Java客户端,区别如下:

  • 功能支持:Redisson支持分布式锁、分布式集合、分布式对象等更丰富的分布式特性。
  • 性能:Redisson在某些场景下性能更优,如分布式锁的实现。
  • 实现方式:Jedis使用直连方式,Redisson使用Netty框架,支持更多的特性。

Jedis和Redisson都是Java对Redis操作的封装,但在使用和功能上存在一些区别。

  1. 使用:Jedis被视为Redis的Java实现的客户端,其API提供了比较全面的Redis命令的支持,它的方法调用与Redis的API保持一致,因此了解Redis的API就能熟练地使用Jedis。而Redisson不仅封装了redis,还封装了对更多数据结构的支持,以及锁等功能,相比于Jedis更加全面。
  2. 功能:相比于Jedis,Redisson进行了更高的抽象,每个方法调用可能进行了一个或多个Redis方法调用。Redisson的宗旨是促进使用者对Redis的关注分离,从而让使用者能够将精力更集中地放在处理业务逻辑上。

9.怎么保证缓存和数据库数据的一致性?

保证缓存和数据库数据一致性的方式有:

  • Write-Through模式:数据写入时,先写入数据库,再写入缓存。
  • Write-Behind模式:数据写入时,先写入缓存,然后异步写入数据库。
  • Cache-Aside模式:数据读取时,先从缓存读取,如果不存在再从数据库读取,并将数据写 入缓存。

保证缓存和数据库数据一致性的方式有多种,以下是几种常见的方法:

  1. 双从复制:这种方式需要至少两台数据库服务器,一台作为主数据库,另一台作为备份数据库。主数据库用于处理写请求,备份数据库用于处理读请求。当主数据库更新数据时,备份数据库也会跟着更新,从而保证缓存和数据库的数据一致性。
  2. 延迟双删:这种方式适用于删除操作。首先,在缓存中删除需要更新的数据,然后在延迟一段时间后,再在数据库中删除相应的数据。这样可以在一定程度上避免因缓存的删除操作和数据库的更新操作不同步而导致的数据不一致问题。
  3. 异步操作:通过异步操作来更新缓存和数据库的数据。这种方式无法保证数据的实时一致性,但可以降低对数据库的访问压力,提高系统的并发处理能力。
  4. 乐观锁:这种方式适用于读多写少的场景。在更新数据时,先获取当前数据的版本号,然后根据版本号进行更新。如果更新失败,说明有其他线程已经修改了数据,需要重新获取最新的数据进行更新。这种方式可以减少对数据库的访问次数,提高系统的性能。
  5. 分布式锁:这种方式适用于分布式系统。通过使用分布式锁来保证同一时间只有一个客户端可以更新数据,从而避免多个客户端同时更新同一份数据导致的数据不一致问题。
  6. 使用消息队列:将缓存和数据库的操作都发送到消息队列中,由消费者线程按照顺序一个一个地执行。这种方式可以保证操作的顺序性和一致性。
  7. 使用事务:对于需要同时对缓存和数据库进行操作的操作,可以使用事务来保证数据的一致性。在事务中,先对缓存进行操作,然后提交事务,最后再对数据库进行操作。如果事务提交成功,说明缓存和数据库的数据一致;如果事务提交失败,则回滚事务,重新进行操作。

10.redis 持久化有几种方式?

Redis支持两种持久化方式:RDB快照和AOF日志文件。

Redis 持久化有三种方式:

  1. AOF(append only file)持久化:采用日志的形式来记录每个写操作,追加到AOF文件的末尾,每次的操作就写入日志,当我们需要恢复数据时,就可以根据日志的记录完整的走一遍流程,恢复数据。
  2. RDB(Redis DataBase)持久化:将某一个时刻的内存数据,以二进制的方式写入磁盘。
  3. 混合持久化方式:Redis 4.0 之后新增的方式,混合持久化是结合了 RDB 和 AOF 的优点,在写入的时候,先把当前的数据以 RDB 的形式写入文件的开头,再将后续的操作命令以 AOF 的格式存入文件,这样既能保证 Redis 重启时的速度,又能减少数据丢失的风险。

你可能感兴趣的:(Java面试八股文,java,开发语言)