redis_02_常见问题

Redis 是什么?它主要用来做什么?

Redis 是一个开源、高性能、非关系型、基于 Key-Value 的内存数据库。它可以用来缓存数据、存储会话数据、任务队列等,还可以用作发布订阅、计数器和排行榜等。

Redis 的数据结构有哪些?请对它们进行简单介绍。

Redis 支持多种数据结构,包括:字符串(String)、哈希表(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)。其中,字符串是最基本的数据结构,而其他结构都是在其基础上构建而成的。

字符串用来存储单个值或者短字符串;哈希表用来存储对象;列表用来存储按插入顺序排序的元素;集合用来存储不重复的元素;有序集合用来存储不重复的元素,并且每个元素都会关联一个分值,可以按照分值排序。

Redis 如何实现分布式?

Redis 可以通过 Redis Cluster 实现分布式。Redis Cluster 使用分区来实现数据分片,每个节点只存储部分数据,从而将整个数据集分配到多个节点中。同时,Redis Cluster 还提供了高可用性、故障转移等机制,使得整个集群具有更好的可靠性和稳定性。

有几种持久化方式?优缺点?

RDB (Redis DataBase): redis按一定周期将内存中的数据同步到磁盘文件中,

RDB优点就是恢复大的数据集的时候,RDB方式会更快些,但是可能会造成数据丢失,因为周期内redis宕机以后,不会记录数据。

AOF (Append Only File): redis会把数据造成更改的命令追加到日志文件中,再下次重启时执行日志文件中的命令,达到数据的还原,

AOF 优点就是可以更好的保护数据不丢失,AOF开启后支持写的QPS会比RDB支持的写的QPS低,因为AOF一般会配置成每秒fsync(同步磁盘)操作,每秒的fsync操作还是很高的,目前很多项目都是混合使用。

Redis 的并发模型是什么?

Redis 使用单线程模型,每个客户端连接都由同一个线程处理。由于 Redis 大部分操作都是 CPU 密集型操作,而非 IO 密集型操作,因此单线程模型能够最大限度地利用 CPU 资源,提高执行效率。

Redis 的过期键是如何处理的?它的过期策略是什么?

Redis 使用惰性过期和定时过期结合的方式来处理过期键。当一个键过期时,Redis 不会立即删除它,而是让它处于过期状态。只有当下一次访问该键时,Redis 才会检测并清除该键。

Redis 支持多种过期策略,包括非精确型的惰性过期(lazy expiration)和精确型的定时过期(active expiration)。其中,惰性过期是基于访问事件的,而定时过期则是使用定时器来检测过期键。

数据库和缓存的处理流程

数据库和缓存的处理流程如下:

  1. 应用程序发送请求:应用程序向数据库或缓存发送读写请求。

  2. 缓存查找数据:如果是读请求,缓存首先查找缓存中是否存在请求的数据。如果数据在缓存中存在,那么直接返回给应用程序;如果不存在,就继续执行第 3 步。

  3. 数据库查找数据:如果请求的数据不在缓存中,那么就需要从数据库中查找。数据库根据请求的指令执行相应的操作,如查询、插入、更新、删除等,并将结果返回给应用程序。

  4. 将数据写入缓存:当数据库返回数据时,应用程序将数据写回缓存中,以便下一次同样的请求可以更快地响应。

  5. 应用程序返回结果:应用程序通过网络将结果返回给客户端。

在这个过程中,如果是写请求,那么缓存往往会先更新数据库中的数据,然后再更新缓存中的数据,以保证数据的一致性。如果缓存中的数据和数据库中的数据不一致,就需要执行一些特定的策略来保证数据的正确性,比如使用读写锁或版本控制等。

缓存雪崩,缓存击穿,缓存穿透?

缓存穿透:key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有,若黑客利用此漏洞进行攻击可能压垮数据库。

解决方案:即使数据库和缓存都查询不到,也要在redis缓存一份数据;另外一种布隆过滤器。

缓存击穿:key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮。

解决方案:热点数据毕竟只有少数,可以设置成永不过期。

缓存雪崩:当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,也会给后端系统(比如DB)带来很大压力。

解决方案:一过期时间加个随机数,保证热点数据不会同是过期。

你的项目哪些功能用到了?

一般项目的登录的Token、修改频率较低的数据放进缓存、分布式锁、幂等性校验等等。

  1. 缓存系统 将频繁查询、计算结果等数据缓存到 Redis 中,可以大大减轻应用程序的计算压力。同时,Redis 支持设置过期时间,能够自动移除失效的缓存数据,避免缓存占用过多内存。

  2. 分布式锁 分布式锁在分布式环境下保证资源的独占性,Redis 可以通过 SETNX 和 EXPIRE 命令来实现分布式锁。这种方案相比于传统的基于数据库的锁,具有更高的性能。

  3. 计数器 Redis 可以通过 INCR 和 DECR 命令来实现计数器,这种方案在高并发场景下具有较好的性能表现。

  4. 发布订阅 Redis 支持发布订阅模式,可以实现消息队列和事件驱动等功能。

  5. 分布式 Session Web 应用程序中,Session 的存储通常是基于 Cookie 或者基于数据库的,但是这两种方案都存在性能问题。而 Redis 的高性能、持久化和分布式特性,使得它成为一种优秀的 Session 存储方案。

除此之外,Redis 还可以应用于排行榜、地理位置信息存储、全文搜索等领域。

怎么保证DB和Redis的数据一致性?

有多种方案可以保证数据库和 Redis 缓存之间的数据一致性,其中比较常见的包括以下三种:

  1. 先更新数据库,再更新缓存

这是最常见的策略。在写操作时,应用程序先向数据库发起写操作,如果操作成功,则再向 Redis 发送更新缓存的指令。这样可以确保 Redis 中的缓存数据和数据库总是一致的。同时,读操作时,先从 Redis 缓存中查找数据,如果没有则从数据库中查询,并将查询结果写入 Redis 缓存中。这样可以保证缓存数据的热点命中率,提高访问性能。

  1. 定期更新缓存

对于一些不是特别关键的数据,可以通过定期刷新缓存来保证数据一致性。应用程序在读取数据时,先从 Redis 缓存中获取数据。如果 Redis 中的数据过期,那么应用程序就从数据库中重新加载数据,并将加载到的数据写入 Redis 缓存中。此时,所有的读请求都会从 Redis 缓存中获取数据,直到 Redis 缓存中的数据过期为止。由于 Redis 缓存中的数据都是合法的,所以无论何时应用程序都可以从 Redis 缓存中获取正确的数据。

  1. 使用消息队列异步更新缓存

当数据写入数据库时,应用程序发送一条消息到消息队列中,消息中包含被修改的数据的键和值。消息队列中的消费者将这些消息处理并更新 Redis 缓存。由于写操作是异步执行的,所以对数据的读操作可能会出现不一致的情况。但是,这种方案可以保证缓存数据最终与数据库中数据一致。需要注意的是,在使用消息队列时,需要考虑消息丢失或消息重发导致数据不一致等问题。为了解决这些问题,可以采用重试机制或者数据恢复机制等。[1][2]

Redis 主从复制的原理是什么?

Redis 主从复制是将一个 Redis 实例的数据复制到另一个 Redis 实例的过程。主 Redis 实例将数据同步到从 Redis 实例,从 Redis 实例只能进行读取操作。Redis 主从复制的原理是主 Redis 实例执行写操作时,会将写操作发送给从 Redis 实例,从 Redis 实例接收到后将数据同步到自己的内存中。