Redis面试题

redis简介

Redis 默认有 16 个数据库,使用select命令切换,库之间数据不共享。

常用命令

dbsize 查看当前一共有多少个键 keys * 查看有哪些键 FLUSHDB 删除当前库的所有key FLUSHALL 删除所有库的所有key move key1 2 把key1移动到2号库 srandmember set 3 随机选取三个数字 zrangebyscore 60 90 包含60-90的 zrangebyscore 60 (90 不包含90的 zrangebyscore (60 (90 不包含60也不包含90的

rdis过期策略

  • redis 持久化就是在指定的时间间隔内将内存中的数据集快照写入磁盘。也就是行话讲的 Snapshot 快照,它恢复时是将快照文件直接读到内存里。

  • redis 会单独创建(fork)一个子进程来进行持久化,会先将数据写入到一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。整个过程中,主进程是不进行任何 IO 操作的,这就确保了极高的性能。

  • 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那 RDB 方式要比 AOF 方式更加的高效。RDB 的缺点是最后一次持久化后的数据可能丢失。

RDB

RDB默认的持久化方案

1分钟内改变了1万次 5分钟内改变了10次 15分钟内改变了1次

禁用 rdb,只需要不设置任何 save 指令,或者给 save 传一个空字符串。save 命令和 FLUSHALL 命令都可以重新生成 dump.rdb 文件,FLUSHALL 生成的 rdb 文件是空的,没有意义。

save 命令执行的时候,全部阻塞,bgsave 执行时会在后台异步进行快照操作,此时还可以响应客户端操作。

优点

  • RDB 是一个非常紧凑的文件。
  • RDB 在保存 RDB 文件时父进程唯一需要做的就是 fork 出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他 IO 操作,所以 RDB 持久化方式可以最大化 redis 性能。
  • 与 AOF 相比,在恢复大的数据集的时候,RDB 更快一些。

缺点

  • RDB 数据丢失风险大。
  • RDB 需要经常 fork 子进程来保存数据集到硬盘上,当数据集比较大时,fork 的过程非常耗时,可能会导致redis 在一些毫秒级不能响应客户端请求。

使用场景

  • 适合大规模的数据恢复
  • 对数据完整性和一致性要求不高

AOF

AOF 以日志的形式来记录每个写操作,将 redis 执行过的所有写指令记录下来(读操作不记录)。

只许追加文件但不可以改写文件,redis 启动之初会读取该文件重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作。

AOF同步策略

  • Always
    • 同步持久化
    • 每次发生数据变更会被立即记录到磁盘
    • 性能差但数据完整性比较好
  • Everysec
    • 出厂默认推荐,异步操作
    • 每秒记录,如果一秒内宕机,有数据丢失
  • No
    • 不同步

修复

AOF 文件损坏使用 redis-check-aof --fix 工具进行修复。

AOF 和 RDB 持久化策略可以一起使用,如果 AOF 启用了,则会优先使用 AOF 文件。

AOF的劣势

相同数据集的数据而言 aof 文件要远大于 rdb 文件,恢复速度慢于 rdb。

aof 运行效率要慢于 rdb,每秒同步策略效率较好,不同步效率和 rdb 相同。

AOF rewrite

AOF 采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制,当 EOF 文件的大小超过所设定的阀值时,Redis 就会启动 AOF 文件的内容压缩,只保留可以恢复数据的最小指令集。可以使用命 bgrewriteaof。

AOF rewrite原理

AOF 文件持续增长而过大时,会 fork 出一条新进程来将文件重写(也是先写临时文件最后再 rename),遍历新进程的内存中数据,每条记录有一条的 Set 语句。

重写 AOF 文件的操作,并没有读取旧的 AOF 文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof 文件,这点和快照有点类似。

触发机制

Redis 会记录上次重写时的 AOF 大小,默认配置是当 AOF 文件大小是上次 rewrite 后大小的一倍且文件大于 64M 时触发。

Redis事务

可以一次执行多个命令,本质是一组命令的集合。一个事务中的命令都会序列化,按顺序地串行话执行而不会被其他命令插入,不许加塞。

redis事务作用

一个队列中,一次性、顺序性、排他性的执行一些列命令。

redis事务常用命令

MULTI 事务开启 EXEC 执行所有事务块内的命令 DISCARD 取消事务,放弃执行事务块内的所有命令 WATCH 监控一个或多个key,如果在事务执行之前这个key被其他命令改动,那么事务将被打断

全部不被执行与部分执行

如果在一个事务中,执行一个命令,这个命令立刻报错的话,那么这个事务内的所有命令都不被执行,比如执行一个不存在的命令只有出错的不被执行。

如果在一个事务中,执行一个命令,这个命令是错的,但一定要到提交事务时才能发现,比如 incr k1,那么这个事务内的其他所有命令都将被执行,只有 incr k1 不被执行。

watch监控

悲观锁

顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿着个数据就会 block 直到它拿到锁。

传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁,读锁,写锁等,都是在做操作之前先上锁。

乐观锁

顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制。

乐观锁适用于多读的应用类型,这样可以提供吞吐量。

乐观锁策略

提交版本必须大于记录当前版本才能执行更新。

Watch指令

类似乐观锁,事务提交时,如果 key 的值已经别的客户端修改,比如某个 list 已经被别的客户端 push/pop 过了,整个事务队列都不会被执行。

主从复制

配置

  • 配从(库)不配主(库)
  • 从库配置
    • 修改配置文件进行配置
      • 开启 daemonize yes
      • 指定 pid 文件的名字
      • 指定端口
      • Log 文件的名字
      • Dump.rdb 名字
    • 在从库执行
      • slaveof 主库 IP 主库端口
      • 每次与 master 断开之后,都需要重新连接,除非你配置进 redis.conf 文件

常用三招

  • 一主二仆
    • 一个主机,两个从机
  • 薪火相传
    • A 是主机,B 是 A 的主机,同时 B 也是 C 的主机,C 是 B 的从机,这样可以减少 A 的写的压力
  • 反客为主

主从复制的原理

  • slave 启动成功连接到 master 之后会发送一个 sync 命令。
  • master 接受到命令启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master 将传送整个数据文件到 salve,以完成一次完全同步。
  • 全量复制
    • salve 服务在接收到数据库文件的数据后,将其存盘并加载到内存中。
    • slave 第一次连接上 master 会执行全量复制。
  • 增量复制
    • Master 继续将新的所有收集到的修改命令依次传给 slave,完成同步,但是只要重新连接 master,一次完全同步将被自动执行。

哨兵模式

一主二仆的模式,master 挂了,salve 不会自动切换为 master,而哨兵模式是 master 挂了,slave 自动切换为 master。

哨兵模式配置

  1. 新建 sentinel.conf 文件,名字绝对不能错
  2. 在 sentinel.conf 配置 sentinel monitor hostname 127.0.0.1 6379 1
  3. 上面最后的数字 1,表示主机挂掉后 salve 投票看让谁称为主机,得票数多少后成为主机启动哨兵
  4. redis-sentinel /usr/local/sentinel.conf

查看集群命令

info replication