Java-常见面试题收集(十三)

本文介绍了Redis作为远程字典服务的用途,包括缓存加速、消息队列、分布式锁和计数器等功能。详细探讨了Redis的数据类型(如字符串、哈希、列表等),展示了如何利用其实现消息队列,以及持久化机制和过期键删除策略。
摘要由CSDN通过智能技术生成

二十二 Redis

1 Redis 作用

  Redis,全称Remote Dictionary Server,即远程字典服务,是一个开源的使用ANSI C语言编写的、支持网络的、基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。它主要用于缓存数据的计算结果、页面内容、数据库查询结果等,以提高数据访问速度和响应速度,从而提升系统性能和用户体验。

  Redis具有多种应用场景,包括但不限于:
    缓存:通过缓存热点数据,减少数据库查询次数,提高访问速度。
    消息队列:实现异步处理和解耦,提高系统的可扩展性和灵活性。
    分布式锁:作为分布式锁的存储层,通过缓存锁信息和锁状态,实现分布式锁和并发控制。
    计数器:通过原子操作实现计数器的自增和自减,支持高并发的计数操作,可用于实现各种排行榜和统计功能。

  Redis支持多种数据类型,包括字符串(String)、哈希(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set),这使得Redis可以根据不同的场景选择合适的数据类型来实现各种功能。此外,Redis还提供持久化服务,使得数据在重启或崩溃后不会丢失,进一步增强了其作为缓存和数据库使用的可靠性。

2 Redis 的数据类型

1.String(字符串):这是 Redis 最基本的数据类型,一个 key 对应一个 value。Redis 的字符串是二进制安全的,这意味着你可以在一个字符串中存储任何数据,比如 JPEG 图片或者序列化的对象。

2.Hash(哈希):Redis hash 是一个键值对集合。Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

3.List(列表):Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

4.Set(集合):Redis 的集合是 string 类型元素的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。

5.Zset(有序集合):Redis 有序集合和集合一样也是 string 类型元素的集合,并且集合成员是唯一的。不同的是每个元素都会关联一个 double 类型的分数。Redis 正是通过分数来为集合中的元素从小到到大进行从小到大的排序。

6.Streams(流):Redis StreamsRedis 5.0 版本引入的新数据类型,用于实现消息队列系统。Streams 是一个包含零个或多个消息的可持久化、可复制的日志。

7.Bitmaps(位图):虽然位图不是 Redis 的一种独立数据类型,但 Redis 提供了位操作命令,允许用户将字符串键当作位数组(bit array)或位图(bitmap)来处理,实现一些高效的位运算操作。

8.HyperLogLog(超对数日志):HyperLogLogRedis 的一种基数统计数据类型,它提供了在允许一定误差的情况下,使用极少的内存空间来统计大量数据的基数的功能。

9.Geospatial(地理空间):Redis 的地理空间索引用于地理位置信息的查询和计算,比如获取某个位置附近的其它位置等。

虽然 Redis 支持多种数据类型,但每个 key 只能对应一种数据类型。也就是说,你不能将一个 key 同时设置为字符串和哈希。此外,Redis 的数据类型并不是固定不变的,随着版本的更新,Redis 可能会引入新的数据类型或改进现有数据类型的功能。

3 Redis 如何实现消息队列功能

  1.基于 List 实现的队列Redis 的 List 数据结构可以很方便地用来实现队列。List 提供了从头部插入(LPUSH)和从尾部弹出(RPOP)或者从尾部插入(RPUSH)和从头部弹出(LPOP)元素的原语操作,这些操作都是原子性的,因此可以很容易地实现一个线程安全的队列。
  生产者:使用 LPUSH 或 RPUSH 将消息放入队列。
  消费者:使用 RPOP 或 LPOP 从队列中取出消息。
  如果需要处理多个消费者竞争同一个消息的情况,可以使用 BLPOP 或 BRPOP 命令,这些命令在队列为空时会阻塞,直到有消息可用。

  2.发布/订阅模型: Pub/Sub,Redis 的发布/订阅模式允许发送者(发布者)发送消息到频道,而接收者(订阅者)可以订阅一个或多个频道以接收消息。
  发布者:使用 PUBLISH 命令将消息发布到指定的频道。
  订阅者:使用 SUBSCRIBE 命令订阅一个或多个频道,并使用 PSUBSCRIBE 命令订阅匹配特定模式的频道。当有消息发布到这些频道时,订阅者会收到消息。
  需要注意的是,发布/订阅模式中的消息是即时发送的,如果订阅者当前不在线,那么它就不会收到这些消息。因此,这种模式更适用于实时通信或事件通知等场景。

  3.Redis 5.0 新增的队列: Stream,Redis 5.0 引入了 Stream 数据类型,它是一个持久化的、可靠的消息队列。Stream 提供了消息的持久化存储,并且支持消费者组的概念,使得多个消费者可以协作处理消息队列。
  生产者:使用 XADD 命令将消息添加到 Stream 中。每个消息都有一个唯一的 ID,并且可以按照时间顺序排列。
消费者组:消费者可以加入一个或多个消费者组,并从 Stream 中读取消息。每个消费者组都有一个或多个消费者,它们共同处理 Stream 中的消息。
  消息确认:消费者处理完消息后,需要发送一个确认信号(XACK 命令),以告知 Stream 该消息已经被处理。如果消费者在处理消息时崩溃,那么未确认的消息可以被其他消费者重新处理。
  Stream 还提供了多种查询和监控功能,使得开发者可以更方便地管理和维护消息队列。

  基于 List 的实现简单直观,适用于简单的队列需求;发布/订阅模型适用于实时通信和事件通知等场景;而 Stream 则提供了更强大和灵活的消息队列功能,适用于复杂的业务场景。

4 Redis 的持久化机制

  1.RDB 持久化:RDB 持久化方式能够在指定的时间间隔能对你的数据进行快照存储。 在默认情况下, Redis 将数据库快照保存在名字为 dump.rdb 的二进制文件中。 在Redis 运行时, RDB 程序将当前内存中的数据库快照保存到磁盘文件中, 在Redis 重启动时, RDB 程序可以通过载入 RDB 文件来还原数据库的状态。

# RDB 自动持久化规则
# 当 900 秒内有至少有 1 个键被改动时,自动进行数据集保存操作
save 900 1
# 当 300 秒内有至少有 10 个键被改动时,自动进行数据集保存操作
save 300 10
# 当 60 秒内有至少有 10000 个键被改动时,自动进行数据集保存操作
save 60 10000

  RDB 的优点:与 AOF 相比,在恢复大的数据集的时候,RDB 方式会更快一些。与 AOF 相比,文件比较小。
  RDB 的缺点:但有可能会产生长时间的数据丢失。

  2.AOF 持久化:Redis 在执行命令的时候,按照配置的策略,定期把命令原本的语句记录一个appendonly.aof 的文件当中,然后通过 fsync 策略,将命令执行后的数据持久化到磁盘中」(不包括读命令)

# AOF 持久化的三种策略
always: 每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全

everysec: 每秒 fsync 一次:足够快,并且在故障时只会丢失 1 秒钟的数据。推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。

no: 从不 fsync :将数据交给操作系统来处理,由操作系统来决定什么时候同步数据。更快,也更不安全的选择。

  AOF 的优点:AOF 可以[更好的保护数据不丢失],一般 AOF 会以每隔 1 秒,通过后台一个线程去执行 fsync 操作,如果 Redis 进程挂了,最多丢失 1 秒的数据AOF 是将命令直接追加到文件末尾的,顺序写,写入性能非常高AOF 日志文件的命令通过非常可读的方式进行记录,这个非常适合做灾难性的误删除紧急回复,如果某人不小心用 flushall 命令清空了所有数据,那么可以将日志文件中的 flushall 删除,然后进行恢复.
  AOF 的缺点:对于同一份数据源来说,一般情况下,AOF 文件比 RDB 数据快照要大由于.aof 的每次命令都会写入,相对于 RDB 来说需要消耗性能也就更多数据恢复比较慢,不适合做冷备

  3.混合持久化:重启 Redis 时,我们很少使用 rdb 来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重写,
但是 AOF 重写性能相对 rdb 来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。
  AOF 在进行文件重写(aof 文件里可能有太多没用指令,所以 aof 会定期根据内存的最新数据生成 aof 文件)时将重写这一刻之前的内存 rdb 快照文件的内容和增量的 AOF 修改内存数据的命令日志文件存在一起,都写入新的 aof 文件,新的文件一开始不叫 appendonly.aof,等到重写完新的AOF 文件才会进行改名,原子的覆盖原有的 AOF 文件,完成新旧两个 AOF 文件的替换。

# 混合持久化配置
aof-use-rdb-preamble yes

5 Redis 过期键删除策略

  对于过期键一般有三种删除策略
  定时删除:在设置键的过期时间的同时,创建一个定时器(timer),让定时器在键的过期时间来临时,立即执行对键的删除操作;
  惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,那就返回该键;
  定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键。至于删除多少过期键,以及要检查多少个数据库,则由算法决定。

  三种策略的优缺比较:

  定时删除策略对内存是最友好的:通过使用定时器,定时删除策略可以保证过期键会尽可能快地被删除,并释放过期键所占用的内存;但另一方面,定时删除策略的缺点是,他对 CPU 是最不友好的:在过期键比较多的情况下,删除过期键这一行为可能会占用相当一部分 CPU 时间,在内存不紧张但是 CPU 时间非常紧张的情况下,将 CPU 时间用在删除和当前任务无关的过期键上,无疑会对服务器的响应时间和吞吐量造成影响;

  惰性删除策略对 CPU 时间来说是最友好的:程序只会在取出键时才对键进行过期检查,这可以保证删除过期键的操作只会在非做不可的情况下进行;惰性删除策略的缺点是,它对内存是最不友好的:如果一个键已经过期,而这个键又仍然保留在数据库中,那么只要这个过期键不被删除,它所占用的内存就不会释放;定时删除占用太多 CPU 时间,影响服务器的响应时间和吞吐量;惰性删除浪费太多内存,有内存泄漏的危险。

  定期删除策略是前两种策略的一种整合和折中:定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响;通过定期删除过期键,定期删除策略有效地减少了因为过期键而带来的内存浪费;定期删除策略的难点是确定删除操作执行的时长和频率。

  Redis 的过期键删除策略:Redis 服务器实际使用的是惰性删除和定期删除两种策略。

6 Redis 八种淘汰策略

1.noeviction(默认策略):当内存不足以容纳新写入数据时,新写入操作会报错。这个策略会保证不会删除任何数据,但是会拒绝所有的写入请求并返回错误给客户端。
2.volatile-lru:针对设置了过期时间的key,使用LRU(Least Recently Used,最近最少使用)算法进行淘汰。这意味着最久未使用的key会被优先删除。
3.volatile-lfu:同样针对设置了过期时间的key,使用LFU(Least Frequently Used,最不经常使用)算法进行淘汰。LFU算法会淘汰那些访问频率最低的key。
4.volatile-ttl:这个策略会淘汰那些设置了过期时间且剩余生存时间(TTL)最短的key。
5.volatile-random:随机淘汰设置了过期时间的key。
6.allkeys-lru:使用LRU算法淘汰所有key中最近最少使用的那些数据。这个策略不区分key是否设置了过期时间。
7.allkeys-lfu:使用LFU算法淘汰所有key中访问频率最低的那些数据。同样,这个策略也不区分key是否设置了过期时间。
8.allkeys-random:加入键的时候如果过限,从所有 key 随机删除

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泰勒疯狂展开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值