Redis篇

Redis有什么优缺点?为什么用Redis查询会比较快

参考答案

(1) Redis有什么优缺点?

Redis 是一个基于内存的数据库,读写速度非常快,通常被用作缓存、消息队列、分布式锁和键值存储数据库。它支持多种数据结构,如字符串、哈希表、列表、集合、有序集合等, Redis 还提供了分布式特性,可以将数据分布在多个节点上,以提高可扩展性和可用性。但是Redis 受限于物理内存的大小,不适合存储超大量数据,并且需要大量内存,相比磁盘存储成本更高。

(2)为什么Redis查询快

  • 基于内存操作: 传统的磁盘文件操作相比减少了IO,提高了操作的速度。
  • 高效的数据结构:Redis专门设计了STRING、LIST、HASH等高效的数据结构,依赖各种数据结构提升了读写的效率。
  • 单线程:单线程操作省去了上下文切换带来的开销和CPU的消耗,同时不存在资源竞争,避免了死锁现象的发生。
  • I/O多路复用:采用I/O多路复用机制同时监听多个Socket,根据Socket上的事件来选择对应的事件处理器进行处理。

Redis的数据类型有哪些?

Redis 常见的五种数据类型:**String(字符串),Hash(哈希),List(列表),Set(集合)及 Zset(sorted set:有序集合)**。

  1. 字符串STRING:存储字符串数据,最基本的数据类型。
  2. 哈希表HASH:存储字段和值的映射,用于存储对象。
  3. 列表LIST:存储有序的字符串元素列表。
  4. 集合SET:存储唯一的字符串元素,无序。
  5. 有序集合ZSET:类似于集合,但每个元素都关联一个分数,可以按分数进行排序。

Redis版本更新,又增加了几种数据类型,

  • BitMap: 存储位的数据结构,可以用于处理一些位运算操作。
  • HyperLogLog:用于基数估算的数据结构,用于统计元素的唯一数量。
  • GEO: 存储地理位置信息的数据结构。
  • Stream:专门为消息队列设计的数据类型。

Redis是单线程的还是多线程的,为什么?

参考答案

Redis在其传统的实现中是单线程的(网络请求模块使用单线程进行处理,其他模块仍用多个线程),这意味着它使用单个线程来处理所有的客户端请求。这样的设计选择有几个关键原因:

  1. 简化模型:单线程模型简化了并发控制,避免了复杂的多线程同步问题。
  2. 性能优化:由于大多数操作是内存中的,单线程避免了线程间切换和锁竞争的开销。
  3. 原子性保证:单线程执行确保了操作的原子性,简化了事务和持久化的实现。
  4. 顺序执行:单线程保证了请求的顺序执行。

但是Redis的单线程模型并不意味着它在处理客户端请求时不高效。实际上,由于其操作主要在内存中进行,Redis能够提供极高的吞吐量和低延迟的响应。

此外,Redis 6.0 引入了多线程的功能,用来处理网络I/O这部分,充分利用CPU资源,减少网络I/O阻塞带来的性能损耗。

说一说Redis持久化机制有哪些

  • AOF 日志:每执行一条写操作命令,就把该命令以追加的方式写入到一个文件里;
  • RDB 快照:将某一时刻的内存数据,以二进制的方式写入磁盘;
  • 混合持久化方式:Redis 4.0 新增的方式,集成了 AOF 和 RBD 的优点;

介绍一下Redis缓存雪崩和缓存穿透,如何解决这些问题?

参考答案

  1. 缓存雪崩是指在某个时间点,大量缓存同时失效,导致请求直接访问数据库或其他后端系统,增加了系统负载。

对于缓存雪崩,可以通过合理设置缓存的过期时间,分散缓存失效时间点,或者采用永不过期的策略,再结合定期更新缓存。

  1. 缓存击穿是指一个缓存中不存在但是数据库中存在的数据,当有大量并发请求查询这个缓存不存在的数据时,导致请求直接访问数据库,增加数据库的负载。典型的场景是当一个缓存中的数据过期或被清理,而此时有大量请求访问这个缓存中不存在的数据,导致大量请求直接访问底层存储系统。

对于缓存击穿,可以采用互斥锁(例如分布式锁)或者在查询数据库前先检查缓存是否存在,如果不存在再允许查询数据库,并将查询结果写入缓存。

  1. 缓存穿透是指查询一个在缓存和数据库都不存在的数据,这个数据始终无法被缓存,导致每次请求都直接访问数据库,增加数据库的负载。典型的情况是攻击者可能通过构造不存在的 key 大量访问缓存,导致对数据库的频繁查询。

对于缓存穿透,可以采用布隆过滤器等手段来过滤掉恶意请求,或者在查询数据库前先进行参数的合法性校验。

如何保证数据库和缓存的一致性

Cache Aside

  • 原理:先从缓存中读取数据,如果没有就再去数据库里面读数据,然后把数据放回缓存中,如果缓存中可以找到数据就直接返回数据;更新数据的时候先把数据持久化到数据库,然后再让缓存失效。
  • 问题:假如有两个操作一个更新一个查询,第一个操作先更新数据库,还没来及删除缓存,查询操作可能拿到的就是旧的数据;更新操作马上让缓存失效了,所以后续的查询可以保证数据的一致性;还有的问题就是有一个是读操作没有命中缓存,然后就到数据库中取数据,此时来了一个写操作,写完数据库后,让缓存失效,然后,之前的那个读操作再把老的数据放进去,也会造成脏数据。
  • 可行性:出现上述问题的概率其实非常低,需要同时达成读缓存时缓存失效并且有并发写的操作。数据库读写要比缓存慢得多,所以读操作在写操作之前进入数据库,并且在写操作之后更新,概率比较低。

Read/Write Through

  • 原理:Read/Write Through原理是把更新数据库(Repository)的操作由缓存代理,应用认为后端是一个单一的存储,而存储自己维护自己的缓存。
  • Read Through:就是在查询操作中更新缓存,也就是说,当缓存失效的时候,Cache Aside策略是由调用方负责把数据加载入缓存,而Read Through则用缓存服务自己来加载,从而对调用方是透明的。
  • Write Through:当有数据更新的时候,如果没有命中缓存,直接更新数据库,然后返回。如果命中了缓存,则更新缓存,然后再由缓存自己更新数据库(这是一个同步操作)。

Write Behind

  • 原理:在更新数据的时候,只更新缓存,不更新数据库,而缓存会异步地批量更新数据库。这个设计的好处就是让数据的I/O操作非常快,带来的问题是,数据不是强一致性的,而且可能会丢。
  • 第二步失效问题:这种可能性极小,缓存删除只是标记一下无效的软删除,可以看作不耗时间。如果会出问题,一般程序在写数据库那里就没有完成:故意在写完数据库后,休眠很长时间再来删除缓存。
Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2023-2025 John Doe
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信