面试突击——Redis

一. memcache和Redis的区别

  • Memcache:代码层次类似Hash

    • 支持简单数据类型
    • 不支持数据持久化存储
    • 不支持主从
    • 不支持分片
  • Redis:

    • 数据类型丰富
    • 支持数据磁盘持久化存储
    • 支持主从
    • 支持分片

二. 为什么Redis那么快?

  • 完全基于内存,绝对部分请求是纯粹的内存操作。
  • 数据结构结构简单,对数据操作也简单。不使用表,不需要对多个表进行关联,存储结构是键值对,查找速度比较快.
  • redis采用单线程(并不是说redis server也是单线程!), 天然的不会出现同步问题,锁竞争,线程切换等额外开销。而之所以使用单线程是因为,cpu并不是限制redis性能的瓶颈,真正的瓶颈依然是磁盘,网路的IO带宽。并且,又多线程需求时,可以开启多个redis来完成对应的需求。
  • 使用多路IO复用模型,非阻塞IO

三. 数据类型

数据类型可以存储的值操作
STRING字符串、整数或者浮点数对整个字符串或者字符串的其中一部分执行操作 对整数和浮点数执行自增或者自减操作
LIST列表从两端压入或者弹出元素 对单个或者多个元素进行修剪, 只保留一个范围内的元素
SET无序集合添加、获取、移除单个元素 检查一个元素是否存在于集合中 计算交集、并集、差集 从集合里面随机获取元素
HASH包含键值对的无序散列表添加、获取、移除单个键值对 获取所有键值对 检查某个键是否存在
ZSET有序集合添加、获取、删除元素 根据分值范围或者成员来获取元素 计算一个键的排名

四. Redis的使用场景

4.1. 从海量Key里查询出某一固定前缀的Key

kyes pattern: 查找所有符合给定模式pattern的key

  • 一次性返回所有匹配的key
  • 键的数量过大会使服务卡顿

可以使用scan cursor [Match pattern][COUNT count]

  • 基于游标的迭代器,需要基于上一次的游标延续之前的迭代过程。
  • 以0作为游标开始一次新的迭代,直到命令返回游标0完成一次遍历。
  • 不保证每次执行都返回给定数量的元素(count数大于key总数的时候)一次返回数量不可控,只能是大概率符合count。
  • 支持模糊查询,即能够返回满足pattern匹配的key

例如:scan 0 match k1* count 10 ,注意,返回的值有可能的是重复的! 因此需要去重!(例如写程序的时候用hashset)

blpop

4.2. 如何通过Redis实现分布式锁

即分布式系统中,访问共同资源时的一种锁的实现。

在分布式场景下,无法使用单机环境下的锁来对多个节点上的进程进行同步。

可以使用 Redis 自带的 SETNX 命令实现分布式锁,setnx key val 就是如果不存在key的话,那么就设置key为val。设置成功返回1, 失败返回0

SET lock_key random_value NX PX 5000

一定要放到一个语句里,保证“获取锁”和“设置超时时间”的原子性。如果设置完setnx以后,程序就挂掉了,那么这个key(锁)就一直被占用!

4.3. 使用Redis做异步队列

除了使用list的rpush, lpop, blpop 以外,可以用pub/sub:主题订阅者模式,来做。

例子:
  • 订阅一个频道:
    • redis-cli1: subscribe myTopic ,之后进入监听状态
    • redis-cli2: subscribe myTopic ,之后进入监听状态
    • redis-cli3: subscribe myTopic ,之后进入监听状态
    • redis-cli4: publish myTopic "hello!!"
      • 这条消息发送出去之后,监听myTopic的3个客户端都收到了“hello!!”这个字符串。

缺点
但需要注意的是,消息的发布是无状态的,也就是无法保证可达。对于发布者来说,消息是即发即失的。 若想解决这个问题,需要用专业的消息队列,如kafka,rocketmq等。

五、Redis如何做持久化

5.1. RDB ( 快照 ) 持久化:保存某一个时间点的全数据快照.

redis服务器加载时,会启用reids.conf文件中的配置信息,里面的:

....

save 900 1   # 就是900秒内如果有1条是写入指令,那么就触发一次快照
save 300 10
save 60 10000

...
stop-writes-on-bgsave-error yes #当设置成yes,
# 就是备份进程若出错了,则主进程就停止
# 接受新的写入操作, 这是为了保证数据一致性!
....

可以根据不同的情况来合理配置。 src目录下的dump.rdb文件,就是redis系统定期备份的rdb文件. 它是一个二进制文件。

5.1.1 生成RDB备份文件的方式:
  • 主动生成
    • SAVE: 阻塞Redis的服务器进程,直到RDB文件被创建完毕。 很少被使用,因为占用了主线程!! 主线程是用来处理client的请求的!!
    • BGSAVE:Fork一个子进程创建RBD文件,不阻塞服务器进程!此时,主进程依然继续工作,子进程将内存中的数据写入临时文件中,因为copy-on-write的机制,父子进程此时会共享相同的物理页面,当(主)父进程处理写请求时,os会为父进程要写的页面创建一个副本(这个副本用于备份),而不是写入共享的页面! RDB文件的载入,一般情况下是自动的,redis服务器启动时,若检测到rdb文件的存在,那么会载入这个文件
      在这里插入图片描述
      在fork时,子进程和父进程共享同一块资源空间,只有当父进程对此空间进行修改时,才会触发给子进程的资源复制,这一机制为copy-on-write. ,juc的copyOnWriteArrayList也是使用的这一原理。
  • 被动生成
    • 根据redis.conf里的save m n 定时触发 (用的是BGSAVE)
    • 主从复制时,主节点自动触发(主节点发送rdb文件给从结点,这时,主节点会触发一次!)
    • 执行debug reload
    • 执行shutdown且没有开启AOF持久化,那么会触发一次RDB持久化
RDB持久化的缺点:
  • 内存数据的全部同步! 数据量大的时候会因为IO而严重影响性能!
  • 可能会因为redis挂掉而丢失从当前到最近一次备份期间的所有数据!

5.2 AOF ( Append-Only-File )持久化:保存写状态

  • 记录下除了查询以外的所有变更数据库状态的指令
  • 以append的形式追加保存到AOF文件中
  • AOF持久化默认是关闭的,可以修改redis.conf来让其生效:
    • appendonly yes # 启动 aof
    • appendfsync everysec/always/no:
      • always: 一旦缓存区发生改变,就立刻将内容写到文件中!
      • everysec: 每隔1s,写入一次
      • no: 什么时候写交给os判断, 一般是等缓存区写满了就写入一次。
日志重写解决AOF文件大小不断增大的问题(例如100条incr 可以用一条add 100实现), 其原理如下:
  • 调用fork(), 创建一个子进程。
  • 子进程把新的AOF写到一个临时文件里,新的AOF是根据内存数据生成对应的命令,并不需要区依赖原来的AOF文件。
  • 主进程持续将新的变动写到内存中,并更新到“旧”的AOF文件里。
  • 重写结束之后,会给主进程一个信号,然后把内存的buff追加到新生成的AOF文件。
  • 用新的AOF替换掉旧的AOF。

5.3 从Redis中恢复数据

其实只要重启就可以了。。

  • 检查AOF是否存在,若存在则直接加载AOF,不再去找RDB
  • 若不存在AOF,则尝试加载RDB

5.4 RDB和AOF的优缺点

  • RDB优点:创建RDB那一瞬间的全部内存数据快照,文件小,恢复快

  • RDB缺点:无法保存最近一次快照之后的数据

  • AOF优点:可读性高,适合保存增量数据,数据不易丢失

  • AOF缺点:文件体积大,恢复时间长

5.5 redis 4.0之后的备份就是混合模式,即RDB-AOF.

rdb用于全量备份,aof用于增量备份,为redis4.0之后的默认备份方式。

bgsave做全量持久化,aof做增量持久化

六、Redis主从同步

主从同步原理

redis的一个Master用于写操作,其他的Slave都是用于读操作。每一个Master和Slave都是一个Redis server实例。期间只保证主从的最终一致性!
在这里插入图片描述
主从同步分为全同步增量同步

  • 全同步过程(上图中的1,2,3,4)
    • Salve发送sync命令给Master请求同步
    • Master进行一次BGSAVE(注意,如果是diskless模式的话,可以不用在本地生成rdb,参考
    • 在进行BGSAVE期间,将所有写操作命令保存至缓存区中。
    • Slave得到Master发送的rdb文件之后进行数据载入。
    • Master再将期间生成的增量写命令发送给slave端。
  • 增量同步(上图中的5):
  • Master接受到用户的操作命令,如果是写命令,就先将操作记录追加到AOF文件中;然后确定将此条写命令传给哪些Salve,然后往响应缓存中写入这条指令。最后将缓存中的数据发送给Slave。(注意,这里并不是收到一条就发送一条,因为需要保证的是最终一致性!)

七、Redis哨兵

但Redis这种主从结构,如果Master服务器当机了,那就全完了。。因此,解决主从同步Master宕机后的主从切换问题: 哨兵模式(Redis Sential)

Redis Sential

Redis Sential是redis官方提供的集群管理工具,其本身也是个独立运行的进程,提供以下几点服务:

  • 监控:检查主从服务器是否运行正常
  • 提醒:当被监控的某个redis服务器出现问题时,sential通过API向管理员或其他应用程序发送故障通知
  • 自动故障迁移:主从切换(主服务器挂了以后,将一个Salve服务器升级成Master服务器,做的事情包括:通知之前的Slave已经修改了Master并告诉新的Master是哪个,当用户发送请求到来时,会返回一个通知,并包括新的Master的地址,使得集群能够正常运行)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值