Redis 面试题

1、为什么要使用缓存

使用缓存的目的就是为了提升读写性能。而实际业务场景下,更多的是为了提升读性能,提高系统的并发量。 Redis 的读写性能比 MySQL 好的多,我们就可以把 MySQL 中的热点数据缓存到 Redis 中,提升读取性能,同时也减轻了 MySQL 的读取压力。

2、什么是 Redis

Redis 是一个开源(BSD 许可)、基于内存、支持多种数据结构的存储系统,可以作为数据库、缓存和消息中间件。它支持的数据结构有字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)、有序集合(sorted sets)等,除此之外还支持 bitmaps、hyperloglogs 和地理空间(geospatial )索引半径查询等功能。

它内置了复制(Replication)、LUA 脚本(Lua scripting)、LRU 驱动事件(LRU eviction)、事务(Transactions)和不同级别的磁盘持久化(persistence)功能,并通过 Redis 哨兵(哨兵)和集群(Cluster)保证缓存的高可用性(High availability)。

3、为什么使用 Redis 而不是用 Memcache

这时候肯定想到的就是做一个 Memcache 与 Redis 区别。

  1. Memcache 仅支持key-value结构的数据类型,Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,hash等数据结构的存储。
  2. 虚拟内存– Redis 当物理内存用完时,可以将一些很久没用到的value 交换到磁盘
  3. 存储数据安全和灾难恢复– Memcache 挂掉后,数据没了,数据不可恢复;; Redis 可以定期保存到磁盘(持久化),可以通过rdb和aof恢复
  4. Memcache 的单个value最大 1m , Redis 的单个value最大 512m 。
  5. Redis 原生就支持集群模式, Redis3.0 版本中,官方便能支持Cluster模式了, Memcached 没有原生的集群模式,需要依赖客户端来实现,然后往集群中分片写入数据。
  6. Memcached 网络IO模型是多线程,非阻塞IO复用的网络模型,原型上接近于 nignx 。而 Redis使用单线程的IO复用模型,自己封装了一个简单的 AeEvent 事件处理框架,主要实现类epoll,kqueue 和 select ,更接近于Apache早期的模式。
  7. 分布式–设定 Memcache 集群,利用 magent 做一主多从; Redis 可以做一主多从。都可以一主一从
  8. Redis 和 Memcache 都是将数据存放在内存中,都是内存数据库。不过 Memcache 还可用于缓存其他东西,例如图片、视频等等。

4、Redis 为什么设计成单线程的

Redis 为什么是单线程的?

Redis选择使用单线程模型主要是由于以下原因:

首先,Redis是基于内存的操作,CPU不是Redis的性能瓶颈,其性能更可能受限于机器内存的大小或网络带宽。

其次,多线程处理会涉及到锁,也会涉及到线程切换而消耗 CPU。采用单线程,避免了不必要的上下文切换和竞争条件,单线程模型可以使Redis的开发和维护更简单。

此外,虽然Redis是单线程的,但它却可以并发处理来自多个客户端的请求,这是通过IO多路复用和非阻塞IO技术实现的。

5、为什么 Redis 单线程模型效率也能那么高

  1. C语言实现,效率高
  2. 纯内存操作
  3. 基于非阻塞的IO多路复用模型
  4. 单线程的话就能避免多线程的频繁上下文切换问题
  5. 拥有丰富的数据结构(全称采用hash结构,读取速度非常快,对数据存储进行了一些优化,比如亚索表,跳表等)

6、说说 Redis 的线程模型

这问题是因为前面回答问题的时候提到了 Redis 是基于非阻塞的IO复用模型。如果这个问题回答不上来,就相当于前面的回答是给自己挖坑,因为你答不上来,面试官对你的印象可能就要打点折扣了。

Redis 内部使用文件事件处理器 (file event handler) ,这个文件事件处理器是单线程的,所以Redis 才叫做单线程的模型。它采用 IO 多路复用机制同时监听多个 socket ,根据 socket 上的事件来选择对应的事件处理器进行处理。

文件事件处理器的结构包含 4 个部分:

  1. 多个 socket
  2. IO 多路复用程序
  3. 文件事件分派器
  4. 事件处理器(连接应答处理器、命令请求处理器、命令回复处理器)

多个 socket 可能会并发产生不同的操作,每个操作对应不同的文件事件,但是 IO 多路复用程序会监听多个 socket,会将 socket 产生的事件放入队列中排队,事件分派器每次从队列中取出一个事件,把该事件交给对应的事件处理器进行处理。

下面来大致说一下这个图:

  1. 客户端 Socket01 向 Redis 的 Server Socket 请求建立连接,此时 Server Socket 会产生一个AE_READABLE 事件,IO 多路复用程序监听到 server socket 产生的事件后,将该事件压入队列中。文件事件分派器从队列中获取该事件,交给连接应答处理器。连接应答处理器会创建一个能与客户端通信的 Socket01,并将该 Socket01 的 AE_READABLE 事件与命令请求处理器关联。
  2. 假设此时客户端发送了一个 set key value 请求,此时 Redis 中的 Socket01 会产生AE_READABLE 事件,IO 多路复用程序将事件压入队列,此时事件分派器从队列中获取到该事件,由于前面 Socket01 的 AE_READABLE 事件已经与命令请求处理器关联,因此事件分派器将事件交给命令请求处理器来处理。命令请求处理器读取 Socket01 的 set key value 并在自己内存中完成 set key value 的设置。操作完成后,它会将 Socket01 的 AE_WRITABLE 事件与命令回复处理器关联。
  3. 如果此时客户端准备好接收返回结果了,那么 Redis 中的 Socket01 会产生一个AE_WRITABLE 事件,同样压入队列中,事件分派器找到相关联的命令回复处理器,由命令回复处理器对 Socket01 输入本次操作的一个结果,比如 ok ,之后解除 Socket01 的AE_WRITABLE 事件与命令回复处理器的关联。

7、为什么 Redis 需要把所有数据放到内存中

Redis 将数据放在内存中可以实现快速的对数据进行读取,如果数据存储在硬盘中,磁盘 I/O 会严重影响 Redis 的性能。而且 Redis 还提供了数据持久化功能,不用担心服务器重启对内存中数据的影响。

8、说一下 Redis 有什么优点和缺点

优点

  1. 数据存在内存中,读取速度快
  2. 支持多种数据结构,包括字符串、列表、集合、有序集合、哈希等
  3. 支持事务,且操作遵守原子性
  4. 拥有队列、数据持久化、主从复制、哨兵、集群、分布式锁等功能

缺点

  • 由于 Redis 是内存数据库,所以,单台机器,存储的数据量,跟机器本身的内存大小。虽然Redis 本身有 Key 过期策略,但是还是需要提前预估和节约内存。如果内存增长过快,需要定期删除数据
  • 如果进行完整重同步,由于需要生成 RDB 文件,并进行传输,会占用主机的 CPU ,并会消耗现网的带宽。不过 Redis 2.8 版本,已经有部分重同步的功能,但是还是有可能有完整重同步的。比如,新上线的备机
  • 修改配置文件,进行重启,将硬盘中的数据加载进内存,时间比较久。在这个过程中, Redis不能提供服务

Redis 是内存数据库,短时间内⼤量增加数据,可能导致内存不够⽤。如果进行完整重同步,由于需要生成 RDB 文件,并进行传输,会占用主机的 CPU ,并会消耗现网的带宽。修改配置文件进行重启时,会将硬盘中的数据加载进内存,时间比较久,在这个过程中, Redis不能提供服务。

9、Redis 的同步机制了解吗?是什么?

Redis 支持主从同步、从从同步。如果是第一次进行主从同步,主节点需要使用 bgsave 命令,再将后续修改操作记录到内存的缓冲区,等 RDB 文件全部同步到复制节点,复制节点接受完成后将RDB 镜像记载到内存中。等加载完成后,复制节点通知主节点将复制期间修改的操作记录同步到复制节点,即可完成同步过程。

10、pipeline 有什么好处,为什么要用 pipeline

使用 pipeline(管道)的好处在于可以将多次 I/O 往返的时间缩短为一次,但是要求管道中执行的指令间没有因果关系。

用 pipeline 的原因在于可以实现请求/响应服务器的功能,当客户端尚未读取旧响应时,它也可以处理新的请求。如果客户端存在多个命令发送到服务器时,那么客户端无需等待服务端的每次响应才能执行下一个命令,只需最后一步从服务端读取回复即可。

11、热点数据和冷数据是什么

热点数据和冷数据主要是对于数据的访问频率来区分的。热点数据通常是被频繁访问的数据,冷数据则是访问频率较低的数据。

为了提升系统的性能,我们通常会将热点数据存储在性能较高的存储介质中,如Redis中。同时,为了防止冷数据占用过多的存储空间,需要对冷数据进行适当的处理,比如限定Redis占用的内存,让Redis根据自身的数据淘汰策略,将热数据保留在内存中。这样既可以保证系统的运行效率,又能节省存储空间。

12、Redis 的过期策略以及内存淘汰机制

在过期策略方面,Redis采取了“定期删除+惰性删除”的策略。Redis默认每隔100ms就随机抽取一些设置了过期时间的key,检查是否过期,如果过期就删除。这种策略既能立即清除过期的数据,对内存友好,又能通过定时器减少占用CPU资源,影响缓存的响应时间和吞吐量。

LRU:最近最少使用淘汰算法(Least Recently Used)。LRU是淘汰最长时间没有被使用的数据

LFU:最不经常使用淘汰算法(Least Frequently Used)。LFU是淘汰一段时间内,使用次数最少的数据

内存淘汰机制:

  1. noeviction: 不会驱逐任何key,表示即使内存达到上限也不进行置换,所有能引起内存增加的命令都会返回error
  2. allkeys-lru: 对所有key使用LRU算法进行删除,优先删除掉最近最不经常使用的key,用以保存新数据
  3. volatile-lru: 对所有设置了过期时间的key使用LRU算法进行删除
  4. allkeys-random: 对所有key随机删除
  5. volatile-random: 对所有设置了过期时间的key随机删除
  6. volatile-ttl: 删除马上要过期的key
  7. allkeys-lfu: 对所有key使用LFU算法进行删除
  8. volatile-lfu: 对所有设置了过期时间的key使用LFU算法进行删除

13、说说Redis持久化机制

Redis是一个支持持久化的内存数据库,通过持久化机制把内存中的数据同步到硬盘文件来保证数据持久化。当Redis重启后通过把硬盘文件重新加载到内存,就能达到恢复数据的目的。 实现:单独创建fork()一个子进程,将当前父进程的数据库数据复制到子进程的内存中,然后由子进程写入到临时文件中,持久化的过程结束了,再用这个临时文件替换上次的快照文件,然后子进程退出,内存释放。

RDB是Redis默认的持久化方式。按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制文件。即Snapshot快照存储,对应产生的数据文件为dump.rdb,通过配置文件中的save参数来定义快照的周期。( 快照可以是其所表示的数据的一个副本,也可以是数据的一个复制品。)

AOF:Redis会将每一个收到的写命令都通过Write函数追加到文件最后,类似于MySQL的binlog。当Redis重启是会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。

当两种方式同时开启时,数据恢复Redis会优先选择AOF恢复。

14、Redis 持久化方式有哪些?以及有什么区别?

Redis 提供两种持久化机制 RDB 和 AOF 机制

RDB是Redis默认的持久化方式。按照一定的时间周期策略把内存的数据以快照的形式保存到硬盘的二进制文件中。即Snapshot快照存储,对应产生的数据文件为dump.rdb,通过配置文件中的save参数来定义快照的周期。( 快照可以是其所表示的数据的一个副本,也可以是数据的一个复制品。)

优点:

  1. 只有一个 dump.rdb 文件 ,方便持久化
  2. 容灾性好,一个文件可以保存到安全的磁盘
  3. 性能最大化,fork 子进程来完成写操作,让主进程继续处理命令,所以是 IO 最大化。(使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 Redis 的高性能)
  4. 数据集大时,比 AOF 的启动效率更高

缺点:

数据安全性低。 RDB 是间隔一段时间进行持久化,如果持久化之间 Redis 发生故障,会发生数据丢失。所以这种方式更适合数据要求不严谨的时候

AOF:Redis会将收到的每一个写命令都通过Write函数追加到文件最后,类似于MySQL的binlog。当Redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。

优点:

  1. 数据安全, AOF 持久化可以配置 appendfsync 属性,使用always,每进行一次命令操作就会记录到 AOF 文件中。
  2. 通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof 工具解决数据一致性问题。
  3. AOF 机制的 rewrite 模式。 AOF 文件没被 rewrite 之前(文件过大时会对命令进行合并重写),可以删除其中的某些命令(比如误操作的 flushall )

缺点:

  1. AOF 文件比 RDB 文件大,且恢复速度慢
  2. 数据集大的时候,比 RDB 启动效率低

15、持久化有两种,那应该怎么选择呢

RDB+AOF的混合方式---------> 结论:RDB镜像做全量持久化,AOF做增量持久化

先使用RDB进行快照存储,然后使用AOF持久化记录所有的写操作,当重写策略满足或手动触发重写的时候,将最新的数据存储为新的RDB记录。这样的话,重启服务的时候会从RDB和AOF两部分恢复数据,既保证了数据完整性,又提高了恢复数据的性能。简单来说:混合持久化方式产生的文件一部分是RDB格式,一部分是AOF格式。----》AOF包括了RDB头部+AOF混写

16、怎么使用 Redis 实现消息队列

一般使用 list 结构作为队列, rpush 生产消息, lpop 消费消息。当 lpop 没有消息的时候,要适当sleep 一会再重试。

  • 面试官可能会问可不可以不用 sleep 呢?list 还有个指令叫 blpop ,在没有消息的时候,它会阻塞住直到消息到来。
  • 面试官可能还问能不能生产一次消费多次呢?使用 pub / sub 主题订阅者模式,可以实现 1:N的消息队列。
  • 面试官可能还问 pub / sub 有什么缺点?在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如 rabbitmq 等。
  • 面试官可能还问 Redis 如何实现延时队列?使用sortedset ,拿时间戳作为 score ,消息内容作为 key 调用 zadd 来生产消息,消费者用zrangebyscore 指令获取 N 秒之前的数据轮询进行处理。

17、说说你对Redis事务的理解

什么是 Redis 事务?原理是什么?

Redis 中的事务是一组命令的集合,是 Redis 的最小执行单位。它可以保证一次执行多个命令,每个事务是一个单独的隔离操作,事务中的所有命令都会序列化、按顺序地执行。服务端在执行事务的过程中,不会被其他客户端发送来的命令请求打断。

它的原理是先将属于一个事务的命令发送给 Redis,然后依次执行这些命令。

Redis 事务的注意点有哪些?

需要注意的点有:

  • Redis 事务是不支持回滚的,不像 MySQL 的事务一样,要么都执行要么都不执行;
  • Redis 服务端在执行事务的过程中,不会被其他客户端发送来的命令请求打断。直到事务命令全部执行完毕才会执行其他客户端的命令。

Redis 事务为什么不支持回滚?

Redis 的事务不支持回滚,但是执行的命令有语法错误,Redis 会执行失败,这些问题可以从程序层面捕获并解决。但是如果出现其他问题,则依然会继续执行余下的命令。这样做的原因是因为回滚需要增加很多工作,而不支持回滚则可以保持简单、快速的特性。

Redis事务功能是通过MULTI、EXEC、DISCARD和WATCH 四个原语实现的 Redis会将一个事务中的所有命令序列化,然后按顺序执行。

1.redis 不支持回滚“Redis 在事务失败时不进行回滚,而是继续执行余下的命令”, 所以 Redis 的内部可以保持简单且快速。

2.如果在一个事务中的命令出现错误,那么所有的命令都不会执行;

3.如果在一个事务中出现运行错误,那么正确的命令会被执行。

1)MULTI命令用于开启一个事务,它总是返回OK。 MULTI执行之后,客户端可以继续向服务器发送任意多条命令,这些命令不会立即被执行,而是被放到一个队列中,当EXEC命令被调用时,所有队列中的命令才会被执行。

2)EXEC:执行所有事务块内的命令。返回事务块内所有命令的返回值,按命令执行的先后顺序排列。 当操作被打断时,返回空值 nil 。 3)通过调用DISCARD,客户端可以清空事务队列,并放弃执行事务, 并且客户端会从事务状态中退出。

4)WATCH 命令可以为 Redis 事务提供 check-and-set (CAS)行为。 可以监控一个或多个键,一旦其中有一个键被修改(或删除),之后的事务就不会执行,监控一直持续到EXEC命令。

18、什么是 bigkey?会存在什么影响?

bigkey 是指键值占用内存空间非常大的 key。例如一个字符串 a 存储了 200M 的数据。

bigkey 的主要影响有:

  • 网络阻塞:获取 bigkey 时,传输的数据量比较大,会增加带宽的压力
  • 超时阻塞:因为 bigkey 占用的空间比较大,所以操作起来效率会比较低,导致出现阻塞的可能性增加
  • 导致内存空间不平衡:一个 bigkey 存储数据量比较大,同一个 key 在同一个节点或服务器中存储,会造成一定影响

19、熟悉哪些 Redis 集群模式

主从复制模式、Sentinel 哨兵模式和 Cluster 模式

  • 主从复制模式是 Redis 最基本的分布式解决方案,其原理是通过主服务器(Master)和从服务器(Slave)的数据复制功能,实现数据的备份和读写分离,从而提高 Redis 的可用性和性能。
  • Sentinel 哨兵模式则是 Redis 高可用性的解决方案。在这种模式下,系统通过监控各个节点的状态,当发现某个节点出现故障时,会自动将该节点从集群中移除,并对其他节点进行故障转移,以保证集群的正常运行。
  • Cluster 模式是 Redis 提供的官方集群模式,采用了数据分片技术,具备高可用、可扩展性、分布式和容错等特性。它的原理是将数据分为多个槽位,每个槽位负责存储一部分数据,通过数据分片的方式来解决数据共享问题,并提供数据复制和故障转移功能。

20、是否使用过 Redis Cluster 集群,集群的原理是什么

使用过 Redis 集群,它的原理是:

  1. 所有的节点相互连接
  2. 节点与节点之间通过二进制协议进行通信
  3. 集群节点不会代理查询
  4. 集群节点挂掉会自动故障转移
  5. 集群消息通信通过集群总线通信,集群总线端口大小为客户端服务端口 + 10000(固定值)
  6. 集群可以相对平滑扩/缩容节点
  7. 数据按照 Slot 存储分布在多个 Redis 实例上
  8. 客户端和集群节点之间通信和通常一样,通过文本协议进行

Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0~16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。

21、Redis Cluster 集群方案什么情况下会导致整个集群不可用

Redis 没有使用哈希一致性算法,而是使用哈希槽。Redis 中的哈希槽一共有 16384 个,计算给定密钥的哈希槽,我们只需要对密钥的 CRC16 取摸 16384。假设集群中有 A、B、C 三个集群节点,不存在复制模式下,每个集群的节点包含的哈希槽如下:

  • 节点 A 包含从 0 到 5500 的哈希槽;
  • 节点 B 包含从 5501 到 11000 的哈希槽;
  • 节点 C 包含从 11001 到 16383 的哈希槽;
  • 这时,如果节点 B 出现故障,整个集群就会出现缺少 5501 到 11000 的哈希槽范围而不可用。

22、Redis 集群架构模式有哪几种

Redis 集群架构是支持单节点单机模式的,也支持一主多从的主从结构,还支持带有哨兵的集群部署模式。

23、说说 Redis 哈希槽的概念

Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0~16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点,集群的每个节点负责一部分hash 槽。

24、Redis 常见性能问题和解决方案有哪些

Redis 常见性能问题和解决方案如下:

  1. Master 最好不要做任何持久化工作,如 RDB 内存快照和 AOF 日志文件
  2. 如果数据比较重要,某个 Slave 开启 AOF 备份数据,策略设置为每秒同步一次
  3. 为了主从复制的速度和连接的稳定性,Master 和 Slave 最好在同一个局域网内
  4. 尽量避免在压力很大的主库上增加从库
  5. 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <-Slave3….;这样的结构方便解决单点故障问题,实现 Slave 对 Master 的替换。如果 Master 挂了,可以立刻启用 Slave1 做 Master,其他不变

25、假如 Redis 里面有 1 亿个 key,其中有 10w 个 key 是以某个固定的已知的前缀开头的,如和将它们全部找出来?

可以使用keys 命令和 scan 命令来查找所有以某个固定前缀开头的 key。

keys 命令需要遍历所有的 key,可能会阻塞 Redis 服务器一段时间。

为了避免阻塞 Redis 服务器,可以使用 scan 命令来逐步扫描所有的 key。SCAN 命令每次返回一部分 key,直到所有的 key 都被扫描完毕。

具体步骤如下:

  1. 使用 SCAN 0 命令开始扫描,该命令会返回一个游标(cursor)和一个包含一部分 key 的列表。
  2. 如果返回的列表不为空,则遍历列表中的所有 key,将匹配到的前缀开头的 key 存储到一个集合(set)中。
  3. 如果返回的列表为空,则表示已经扫描完所有的 key,停止扫描。
  4. 如果集合中还有未处理的 key,则使用 SCAN 命令继续扫描,将新的匹配到的前缀开头的 key 添加到集合中。
  5. 如果集合中没有未处理的 key,则表示已经找到了所有以某个固定前缀开头的 key。

需要注意的是,SCAN 命令在扫描过程中可能会阻塞一段时间,因此需要在客户端设置超时时间,以避免长时间的等待。

1. 使用 keys 命令

直接使用 keys 命令查询,但是如果是在生产环境下使用会出现一个问题,keys 命令是遍历查询的,查询的时间复杂度为 O(n),数据量越大查询时间越长。而且 Redis 是单线程,keys 指令会导致线程阻塞一段时间,会导致线上 Redis 停顿一段时间,直到 keys 执行完毕才能恢复。这在生产环境是不允许的。除此之外,需要注意的是,这个命令没有分页功能,会一次性查询出所有符合条件的 key 值,会发现查询结果非常大,输出的信息非常多。所以不推荐使用这个命令。

2. 使用 scan 命令

scan 命令可以实现和 keys 一样的匹配功能,但是 scan 命令在执行的过程不会阻塞线程,并且查找的数据可能存在重复,需要客户端操作去重。因为 scan 是通过游标方式查询的,所以不会导致Redis 出现假死的问题。Redis 查询过程中会把游标返回给客户端,单次返回空值且游标不为 0,则说明遍历还没结束,客户端继续遍历查询。scan 在检索的过程中,被删除的元素是不会被查询出来的,但是如果在迭代过程中有元素被修改,scan 不能保证查询出对应元素。相对来说,scan 指令查找花费的时间会比 keys 指令长。

26、如果有大量的 key 需要设置同一时间过期,一般需要注意什么?

如果有大量的 key 在同一时间过期,那么可能同一秒都从数据库获取数据,给数据库造成很大的压力,导致数据库崩溃,系统出现 502 问题。也有可能同时失效,那么 Redis 会出现短暂的卡顿问题。所以为了预防这种问题的发生,最好给数据的过期时间加一个随机值,让过期时间更加分散。

27、什么情况下可能会导致 Redis 阻塞?

Redis 产生阻塞的原因主要有内部和外部两个原因导致:

内部原因

  1. 如果 Redis 主机的 CPU 负载过高,也会导致系统崩溃
  2. 数据持久化占用资源过多
  3. 对 Redis 的 API 或指令使用不合理,导致 Redis 出现问题

外部原因

外部原因主要是服务器的原因,例如服务器的 CPU 线程在切换过程中竞争过大,内存出现问题、网络问题等。

28、缓存和数据库谁先更新呢?

29、怎么提高缓存命中率?

主要常用的手段有:

  1. 提前加载数据到缓存中
  2. 增加缓存的存储空间,提高缓存的数据
  3. 调整缓存的存储数据类型
  4. 提升缓存的更新频率

30、Redis 如何解决 key 冲突?

Redis 如果 key 相同,后一个 key 会覆盖前一个 key。如果要解决 key 冲突,最好给 key 取好名区分开,可以按业务名和参数区分开取名,避免重复 key 导致的冲突。

31、Redis 报内存不足怎么处理?

Redis 内存不足可以这样处理:

  1. 修改配置文件 redis.conf 的 maxmemory 参数,增加 Redis 可用内存
  2. 设置缓存淘汰策略,提高内存的使用效率
  3. 使用 Redis 集群模式,提高存储量

32、缓存雪崩、缓存穿透、缓存击穿、缓存预热、缓存更新、缓存降级等问题

缓存雪崩是指在设置缓存时采用了相同的过期时间,导致缓存在某一时刻同时失效,所有的请求都转发到数据库,使得数据库压力剧增。解决这一问题的策略通常是采取不同的过期时间,让缓存的失效时间分散。

缓存穿透是指查询一个根本不存在的数据,缓存中也不会有,这种请求会直接打到数据库上,造成数据库压力增大。解决方法可以是用布隆过滤器提前过滤掉这些无效的请求,或者在缓存中存储空对象。

缓存击穿与缓存雪崩类似,但规模较小,指的是某一个热点的key失效后,大量并发集中对其进行访问。解决方案可以是设置热点数据永不过期,或者加互斥锁。

缓存预热则是在系统启动之初,将可能会被访问的数据全部加载到缓存中,这样可以避免在系统正式运行后,由于大量请求导致缓存未命中,进而频繁访问数据库的问题。

缓存更新,一般有两种策略:一种是主动更新,即在数据发生变化时立即更新缓存;另一种是被动更新,即只有在访问数据时才检查数据是否过期,如果过期则更新缓存。

缓存降级,这是当缓存服务出现问题或者宕机时,可以暂时将请求转移到其他的服务上,以保证系统的正常运行。

33、Redis 的数据类型,以及每种数据类型的使用场景

1、String

最基本的数据类型,常规的set/get操作,一般做一些复杂的计数功能的缓存。

  • dy点赞某个视频或商品,点一次加一次
    • 使用incr key 获得多少人喜欢
  • 对于文章是否喜欢
    • 使用incr key 获得多少人喜欢

2、List

List的数据结构,可以做简单的消息队列的功能。

  • 公众号的订阅的消息
    • 关注的人发布文章,就会到我的List lpush likearticle:id 文章id
    • 查看自己订阅的文章 lrange likearticle:id 0 9

3、Hash

Hash 这里value存放的是结构化的对象,比较方便操作其中的某个字段。

  • 早期购物车设计

4、Set

Set 无重复值的集合。利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。

  • 抽象小程序
    • 将所有抽奖用户 sadd key 用户ID
    • 显示多少人参加 SCARD key
    • 从set中任意选取N个中奖人
      • SRANDMEMBER key 2 随机抽奖两个人,元素不删除
      • SPOP key 2 随机抽奖两个人,元素会删除

5、Zset

sorted set,在 set 的基础上加了一个score分数值

  • 根据商品销售对商品进行排序显示
  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值