华为OD技术面真题 - 数据库Redis - 2

文章目录

说说Redis的持久化机制

Redis是内存数据库,如果不提供持久化机制,当redis进程退出或者宕机时,数据会丢失。redis为了保证重启/宕机等情况保证数据不全部丢失,提供了持久化机制。

Redis提供三种持久化机制:

  • 快照(RDB)
  • 可追加文件(AOF)
  • RDB和AOF混合持久化

RDB持久化

RDB持久化本质上是创建当前Redis数据的快照RDB文件(副本)。有了RDB文件之后,在发生程序崩溃/重启可利用RDB恢复数据库内容,Redis默认的持久化机制。

RDB持久化触发方式:

  • 手动触发:
    • 手动执行save命令:阻塞当前Redis服务器,直到RDB过程完成为止,对于内存 比较大的实例会造成长时间阻塞,线上环境不建议使用。
    • 手动执行bgsave命令:Redis进程执行fork操作创建子进程,RDB持久化过程由子 进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。
  • 自动触发:
    • redis.conf配置文件默认会有save m n,即在m秒内有n次修改时,自动触发bgsave生成rdb文件。
    • 默认情况下执行shutdown命令,如果没有开启aof持久化,也会自动触发save命令。

RDB持久化的优缺点:

  • 优点:
    • 文件体积小
    • 读取RDB文件恢复数据快。
  • 缺点:
    • RDB方式实时性不够,无法做到秒级的持久化;
    • fork 子进程有性能和内存压力。

RDB也是进行主从同步数据的载体。

AOF持久化

AOF的出现是为了解决 RDB 数据丢失窗口过大的问题,提供更好的更好实时性保存的持久化机制。通过更改redis.conf配置文件中appendonly yes来启用AOF持久化。AOF持久化本质上看作一个操作日志文件,通过记录更改数据库的命令,然后落盘到文件中,以达到发生程序崩溃/重启时重放命令恢复数据,。

AOF的持久化功能实现可分为以下步骤;

  1. 命令追加(append):所有写命令会追加到AOF缓冲区中。
  2. 文件写入(write):将 AOF 缓冲区的数据写入到 AOF 文件中,此步是将AOF缓存区数据写入到操作系统内核缓冲区。此时并没有进行数据落盘
  3. 文件同步(fsync):根据appendfync配置,redis会按照指定频率,调用fync函数,强制数据落盘,保证数写入磁盘文件。这步执行完成后才代表数据真正被保存

redis中提供appendfync策略有以下几种:

  • always: 同步写回,执行写命令之后,立即执行命令追加文件写入步骤,同时主线程调用fsync命令,阻塞同步直到数据落盘。最安全的一种策略,理论上不会丢失数据,同时性能最差
  • Everysec: 每秒写回,每个写命令执行完,先把日志写到AOF文件的内存缓冲区并执行write操作,后台线程每隔一秒执行fync写入磁盘;性能 + 实时性综合的方案
  • No:操作系统控制的写回,reids不会主动执行fsync命令。实时性最差, 性能最好的方案。

上面提高AOF本质是以追加方式记录Redis已经执行的写命令,随着时间越来越长,AOF文件会变得越来越大。如果不加以控制,AOF文件越大,导致数据恢复也越慢,基于此Redis提供AOF重写机制,限制AOF文件不断增长。AOF重写机制原理是通过读取数据库中的键值对来实现的,程序无须对现有 AOF 文件进行任何读入、分析或者写入操作。 ,步骤大概如下

  1. AOF重写会执行大量写操作,reids将AOF重写使用子进程执行。
  2. AOF 文件重写期间,Redis 还会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新 AOF 文件期间,记录服务器执行的所有写命令。当子进程完成创建新 AOF 文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新 AOF 文件的末尾,使得新的 AOF 文件保存的数据库状态与现有的数据库状态一致。
  3. 服务器用新的 AOF 文件替换旧的 AOF 文件,代表重写的完成。

混合模式

Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。简单来说,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。

混合模式的优点:

  • 快照不用很频繁地执行,这就避免了频繁 fork 对主线程的影响
  • AOF 日志也只用记录两次快照间的操作,也就是说,不需要记录所有操作了,因此,就不会出现文件过大的情况了,也可以避免重写开销。
  • 既能享受到 RDB 文件快速恢复的好处,又能享受到 AOF 只记录操作命令的简单优势。

不同持久化方案适合什么场景

只使用RDB的场景:

  • 缓存型业务
  • 数据可从关系型数据库或其它途径恢复
  • 容忍数据少量数据丢失。

只使用AOF场景:

  • 可容忍性能下降
  • 数据非常重要
  • 不希望丢失数据

混合模式场景:

  • 生产环境,核心业务
  • 既要保证数据不能丢失
  • 又要保证redis重启恢复数据快

Redis内存淘汰策略了解吗

Redis 的内存淘汰策略只有在运行内存达到了配置的最大内存阈值时才会触发,这个阈值是通过 redis.confmaxmemory 参数来定义的。

Redis提供以下几种内存淘汰策略:

  • no-eviction:默认内存淘汰策略,禁止驱逐数据,当内存不足以容纳新写入数据时,新写入操作会报错。
  • volatile-lru:从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。
  • volatile-ttl:从已设置过期时间的数据集中挑选将要过期的数据淘汰。
  • volatile-random: 从已设置过期时间的数据集中任意选择数据淘汰。
  • allkeys-random: 从所有数据集中任意选择数据淘汰。
  • volatile-lfu:从已设置过期时间的数据集中挑选最不经常使用的数据淘汰。
  • allkeys-lfu: 从所有数据集中挑选最不经常使用的数据淘汰。

Redis如何做内存优化

  1. 压缩存储:Redis 5.0 版本引入了对字符串的压缩存储功能,可以在字符串的存储和传输中进行压缩,从而降低内存占用。activate-key-compression配置
  2. 设置过期时间:对于不需要永久保存的数据,可以设置过期时间来释放不再需要的键值对,以及时释放内存。
  3. 分片: 当数据量较大时,可以通过将数据分散存储在多个 Redis 节点上来降低单个节点的内存压力。
  4. 选择合适数据类型:Redis 提供了多种数据结构,选择合适的数据结构可以有效降低内存占用。例如,使用 Bitmaps 来存储大规模的布尔值,使用 HyperLogLog 来进行基数估算等。

什么是Redis事务

Redis 事务是通过 MULTI 和 EXEC 将多个命令打包顺序执行的一种机制,能够保证事务执行期间不会被其他客户端的命令打断。Redis 事务不支持回滚,也不具备关系型数据库事务的完整 ACID 特性。

实际开发过程中,不太推荐使用Redis事务。

Redis事务怎么用

Redis通过MULTI,EXECDISCARDWATCH等命令来实现事务。

常见的事务执行操作

复制代码
# 开启事务
MULTI

SET NAME REDIS
...
GET NAME

EXEC/DISCARD

上述命令的步骤简单解释以下:

  • MULTI: 开启事务,开启事务之后可以输入多个命令,Redis 不会立即执行这些命令,而是将它们放到队列
  • 输入一些REDIS命令,命令不会立即执行,以先进先出的顺序存进队列。
  • EXEC / DISCARD: EXEC表示执行存入队列的命令。DISCARD取消执行队列中的命令,清空所有保存的命令。

WATCH命令用于监听指定的key,当调用EXEC命令执行事务时,如果一个被WATCH命令监视的key被其它客户端/SESSION修改,整个事务都不会被执行。WATCH命令必须在MULTI之前指定。

复制代码
# 客户端1
SET NAME REDIS
WATCH NAME 

MULTI
SET NAME REDIS2


# 客户端2执行
SET NAME REDIS1

# 客户端1然后执行
EXEC

上述这两种操作序列会导致客户端1的事务中所有命令全部被取消。

额外注意WATCH使用中的几点:

  • WATCH命令必须在MULTI之前指定。
  • 如果被WATCHkey和修改key的命令处于同一个Session中,事务中的命令不会被取消。

REDIS事务支持原子性、持久性吗

原子性的定义:单个事务,为一个不可分割的最小工作单元,指的是一个事务中的操作要么全部成功,要么全部失败。REDIS事务处于执行队列中的命令,存在某个命令执行过程出现错误后,后续命令仍然可以继续执行,并且REDIS不支持回滚。 这里可以看出REDIS事务既不能保证同时成功也不能保证同时失败,所以Redis不支持原子性.

持久性的定义:事务一旦提交,结果永久生效。 这里需要联系到REDIS的持久化机制,RDB机制和AOF机制的fync策略为everysecno都存在可能丢失数据的情况,不能满足持久性。不过当使用AFO并且策略设置为always理论上不会丢失数据,满足持久性。

怎么解决Redis中的大key问题

redis中的大key问题就是redis中一个key对象的数据所占用的内存比较大,这就是大key问题。

判断大key的标准从以下两种角度出发:

  • 字符串类型的value超过阈值(阈值可据情况更改,推荐1MB)
  • 符合类型(List Hash等)value包含的元素个数超过阈值(阈值可根据情况更改)

大key的危害主要体现在:

  • 执行速度慢:redis在操作大key时会比较耗时。
  • 网络压力大:如果每次获取大key的数据,数据量大,会加大网络压力。
  • 阻塞其他操作。某些对大Key的操作可能会导致Redis实例阻塞。例如,使用DEL命令删除一个大Key时,可能会导致Redis实例在一段时间内无法响应其他客户端请求,从而影响系统的响应时间和吞吐量。
  • 主从同步延迟。当Redis实例配置了主从同步时,大Key可能导致主从同步延迟。由于大Key占用较多内存,同步过程中需要传输大量数据,这会导致主从之间的网络传输延迟增加,进而影响数据一致性。

常见大key的解决方案:

  • 分割大key:将一个 bigkey 分割为多个小 key。将数据按一定规则分段存储。
  • 清理无效的数据:例如对于list和set类型,value值可能持续增加,需要定时的对 list 和 set 进行清理。
  • 压缩:通过序列化或者压缩的方法对 value 进行压缩,使其变为较小的 value。
  • 预防大key出现:通过监控系统,监控 Redis 中的内存占用大小和网络带宽的占用大小,以及固定时间内的内存占用增长率,当超过设定的阈值的时候,进行报警通知处理。
相关推荐
xuekai200809011 小时前
Oracle 19C 最简单快速安装方式
数据库·oracle
码农水水2 小时前
小红书Java面试被问:mTLS(双向TLS)的证书验证和握手过程
java·开发语言·数据库·redis·python·面试·开源
dyyx1112 小时前
Python GUI开发:Tkinter入门教程
jvm·数据库·python
2401_836121602 小时前
更优雅的测试:Pytest框架入门
jvm·数据库·python
我真的是大笨蛋2 小时前
MySQL临时表深度解析
java·数据库·sql·mysql·缓存·性能优化
九皇叔叔2 小时前
【02】微服务系列 之 初始化工程
java·数据库·微服务
你想考研啊2 小时前
win11配置maven
java·数据库·maven
南屿欣风2 小时前
MySQL Binlog 数据恢复实战
数据库·mysql
DomDanrtsey2 小时前
oracle查询某数据库用户下哪些表的索引没有被使用到?
数据库·oracle