redis缓存知识点

目录

redis的特点

redis的常见的5种数据结构:

 redis提供的功能

redis的持久化

RDB,Redis默认开启

RDB 有两种触发方式,分别是自动触发和手动触发

RDB优点

RDB 的缺点

常用的RDB配置

AOF

AOF 的优点

AOF 的缺点

AOF常用配置

redis重启

Redis高可用集群

特点

key的过期失效机制

缓存达到最大容量时,redis提供的8种淘汰策略


redis的特点

  1. 单线程异步IO,通常使用多线程的场景,是因为磁盘IO操作耗时,造成CPU空闲等待,而不能是CPU发挥最大的性能,因此采用多线程可以使CPU达到充分的使用,而Redis是基于内存的,数据的读写不再是造成性能低下的原因,因此单线程不仅不会使CPU空闲反而会因为单线程的原因避免的线程切换带来的性能开销,因此Redis采用单线程。
  2. 支持持久化,所以redis不仅可以做缓存,也能做nosql数据库
  3. 多数据结构:String、Hash、List、Set、ZSet、HyperLogLog、Geo
  4. 提供主从模式以及cluser集群部署机制

redis的常见的5种数据结构:

类型简介特性场景
String二进制安全可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M普通的k,v存储都可以,也可以利用setnx命令实现分布式锁
Hash键值对集合,即编程语言中的Map类型适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去)存储、读取、修改用户属性
List链表(双向链表)增删快,提供了操作某一段元素的API1,最新消息排行等功能(比如朋友圈的时间线) 2,消息队列
Set哈希表实现,元素不重复1、添加、删除,查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作

1、共同好友

2、利用唯一性,统计访问网站的所有独立ip(HyperLogLog更适合)

3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐

ZSet将Set中的元素增加一个权重参数score,元素按score有序排列数据插入集合时,已经进行天然排序

 1、排行榜 2、带权重的消息队列 3、延时队列使用时间戳做score

另外还有:

bitmap、hyperloglog可以用来做大规模数据的去重统计

geo计算地理位置,位置距离计算,根据半径计算位置,计算范围内的位置有哪些

 redis提供的功能

  1. pub/sub,订阅发布功能,可以用作注册中心
  2. pipeline,可以批量执行一组指令,所有指令执行完成后,一次性返回所有结果。可能会出现某条指令执行失败但大部分都执行成功的情况,适合对可靠性要求不是很高和实时性要求不高的场景,可以避免频繁应答。
  3. lua脚本
  4. 事务,redis提供的不是严格的事务,redis只保证串行执行命令,并且能保证全部执行,但是执行命令失败时不会回滚,而会继续执行下去

redis的持久化

RDB,Redis默认开启

RDB 有两种触发方式,分别是自动触发和手动触发

  1. save(阻塞)
    该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。
    显然该命令对于内存比较大的实例会造成长时间阻塞,这是致命的缺陷,为了解决此问题,Redis提供了第二种方式。
  2. bgsave(非阻塞)
    执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短

RDB优点

  1. 把内存中的数据集以快照的方式写入磁盘,采用二进制压缩存储。可以配置保存时间间隔和变更量,适合用于不同时间段的灾备。保存了 Redis 在某个时间点上的数据集。 比如说,你可以在最近的 24 小时内,每小时备份一次 RDB 文件,并且在每个月的每一天,也备份一个 RDB 文件。 这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。因此RDB 非常适用于灾难恢复
  2. fork子进程进行RDB保存保存操作不影响主进程redis服务:父进程在保存 RDB 文件时唯一要做的就是 fork 出一个子进程,然后这个子进程就会处理接下来的所有保存工作,父进程无须执行任何磁盘 I/O 操作。
  3. RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快

RDB 的缺点

  1. 如果在快照保存完成前服务器宕机会造成数据丢失。如果你需要尽量避免在服务器故障时丢失数据,那么 RDB 不适合你。 虽然 Redis 允许你设置不同的保存点(save point)来控制保存 RDB 文件的频率, 但是, 因为RDB 文件需要保存整个数据集的状态, 所以它并不是一个轻松的操作。 因此你可能会至少 5 分钟才保存一次 RDB 文件。 在这种情况下, 一旦发生故障停机, 你就可能会丢失好几分钟的数据。
  2. 保存快照时可能导致服务短时间不可用。每次保存 RDB 的时候,Redis 都要 fork() 出一个子进程,并由子进程来进行实际的持久化工作。Redis是单线程的,所以在fork阶段会造成服务短时间不可用。 在数据集比较庞大时, fork() 可能会非常耗时,由于redis是单线程,因此在 fork()出一个子进程的过程中,造成服务器在某某毫秒内停止处理客户端; 如果数据集非常巨大,并且 CPU 时间非常紧张的话,那么这种停止时间甚至可能会长达整整一秒。 虽然 AOF 重写也需要进行 fork() ,但无论 AOF 重写的执行间隔有多长,数据的耐久性都不会有任何损失。为了避免这种情况,我们可以通过主从部署的方式,让耗时的保存操作如:bgsave操作,在从服务上运行,这样就不会影响主服务的运行。

常用的RDB配置

#900秒(15分钟),且至少1次变更后,将会进行把数据写入磁盘的操作
#不写磁盘的话就把所有 "save" 设置注释掉就行了。
save 900 1

#当进行RBD bgsave的时候发生错误,是否停止接受写操作,默认no
stop-writes-on-bgsave-error no

#是否压缩RDB文件
rdbcompression yes

#是否开启RDB文件的校验,在写入文件和读取文件时都起作用。
#关闭将带来10%的性能提升,但是无法但是数据损坏时无法发现
rdbchecksum yes                                              

# 当redis保存RDB文件时,如果启用了以下选项,每生成32 MB数据,文件将被fsync-ed。 
# 这很有用,以便以递增方式将文件提交到磁盘并避免大延迟峰值。
rdb-save-incremental-fsync yes

# rdb文件名称
dbfilename dump.rdb
 
# 文件备份目录
dir ./

AOF

AOF 的优点

  1. AOF以日志的形式进程存储,记录redis每个写入和删除命令,AOF 的运作方式是不断地将命令追加到文件的末尾。因此对 AOF 文件的写入不需要进行 seek 而是直接追加在最后。
  2. AOF可以设置不同的同步策略。三个选项:
    1).appendfsync always 每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全。
    2).appendfsync everysec 每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
    3).appendfsync no 从不 fsync :将数据交给操作系统来处理。更快,也更不安全的选择。
  3. AOF文件出错,日志因为某些原因而包含了未写入完整的命令(比如写入时磁盘已满,写入中途停机,等等), redis-check-aof 工具也可以轻易地修复这种问题。redis-check-aof --fix <filename>
  4. Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。新 AOF 文件创建完毕后,Redis 才会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。
    auto-aof-rewrite-percentage 100 
    auto-aof-rewrite-min-size 64mb
    如:如果你对一个计数器调用了 100 次 INCR key , 那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100 条记录(entry)。然而在实际上, 只使用一条SET key value [EX seconds] [PX milliseconds] [NX|XX]命令已经足以保存计数器的当前值了, 其余 99 条记录实际上都是多余的。
  5. AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。

AOF 的缺点

  • 对于相同的数据集来说,因为AOF采用命令有序的保存,所有AOF 文件的体积通常要大于 RDB 文件的体积。
  • 根据所使用的同步策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。
  • AOF 在过去曾经发生过这样的 bug : 因为个别命令的原因,导致 AOF 文件在重新载入时,无法将数据集恢复成保存时的原样。

默认情况下,redis打开RDB功能,如果想使用AOF,可以通过 CONFIG SET appendonly yes 命令设置,但这种方式在服务器重启之后, 就会被遗忘,还可以在redis.conf文件中配置 appendonly yes,这样服务器重启后,程序会按配置文件来启动服务器。RDB和AOF功能可以同时使用。

AOF常用配置

#默认情况下,Redis是异步的把数据导出到磁盘上。这种模式在很多应用里已经足够好,但Redis进程出问题或断电时可能造成一段时间的写操作丢失(这取决于配置的save指令),为了解决这种情况Redis提供aof持久化方式
#是否开启AOF
appendonly no
#AOF文件名称
appendfilename "appendonly.aof"
#AOF文件,同步策略
# no:不要立刻刷,只有在操作系统需要刷的时候再刷。比较快。
# always:每次写操作都立刻写入到aof文件。慢,但是最安全。
# everysec:每秒写一次。默认方案
appendfsync everysec

# 如果AOF的同步策略设置成 "always" 或者 "everysec",并且后台的存储进程(后台存储或写入AOF 日志)会产生很多磁盘I/O开销。某些Linux的配置下会使Redis因为 fsync()系统调用而阻塞很久。
# 注意,目前对这个情况还没有完美修正,甚至不同线程的 fsync() 会阻塞我们同步的write(2)调用。
# 为了缓解这个问题,可以用下面这个选项。它可以在 BGSAVE 或 BGREWRITEAOF 处理时阻止fsync()。
# 这就意味着如果有子进程在进行保存操作,那么Redis就处于"不可同步"的状态。
# 这实际上是说,在最差的情况下可能会丢掉30秒钟的日志数据。(默认Linux设定)
# 如果把这个设置成"yes"带来了延迟问题,就保持"no",这是保存持久数据的最安全的方式。
no-appendfsync-on-rewrite no
 
# 自动重写AOF文件。如果AOF日志文件增大到指定百分比,Redis能够通过 BGREWRITEAOF 自动重写AOF日志文件。
# 工作原理:Redis记住上次重写时AOF文件的大小(如果重启后还没有写操作,就直接用启动时的AOF大小)
# 这个基准大小和当前大小做比较。如果当前大小超过指定比例,就会触发重写操作。你还需要指定被重写日志的最小尺寸,这样避免了达到指定百分比但尺寸仍然很小的情况还要重写。
# 指定百分比为0会禁用AOF自动重写特性。
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
 
# 如果设置为yes,如果一个因异常被截断的AOF文件被redis启动时加载进内存,redis将会发送日志通知用户。如果设置为no,redis将会拒绝启动。此时需要用"redis-check-aof"工具修复文件。
aof-load-truncated yes
 
# [RDB file][AOF tail]
# 加载时Redis识别出AOF文件以“REDIS”开头字符串,
# 并加载带此前缀的RDB文件,然后继续加载AOF
# 尾巴。
aof-use-rdb-preamble yes

redis重启

redis持久化RDB是默认开启的,AOF通过主动配置是否开启(appendonly  yes), redis重启会先去判断是否存在aof文件,如果存在就根据AOF文件启动,如果不存在则根据RDB文件启动。

Redis高可用集群

特点

支持主从同步,提供cluster集群部署模式,保证集群的高并发。通过sentinel哨兵监控Redis主服务器的状态,当主节点挂掉时,在从节点中根据一定的选举策略选出新的主节点,并调整其他从节点的新主节点为选出的新主节点。如此保证服务的高可用。

主节点选举策略主要遵循以下规则:

  1. 选择健康状态从节点(排除主观下线、断线),排除5秒钟没有心跳的、排除主节点失联超过10*down-after-millisecends
  2. 选择slave-priority高的从节点优先级列表,优先级高的最容易被选中
  3. 复制偏移量越大越容易选中,即复制的数据最多的slave最容易被选中
  4. redis节点都有一个runid,类似于身份标识,选择runid小的最容易被选中

redis-cluster采用分片机制,键空间被分割为 16384 个槽(slot),分布在所有的mater节点上,每个master节点负责一部分slot,数据操作是按照HASH_SLOT = CRC16(key) mod 16384 算法计算具体key在哪个slot上,由哪个master处理。

Redis的三种清除策略:

  • 被动删除:当读/写一个已经过期的key时,会触发惰性删除策略,直接删除掉这个过期key
  • 主动删除:由于惰性删除策略无法保证冷数据被及时删掉,所以Redis会定期主动淘汰一批已过期的key
  • 当前已用内存超过maxmemory限定时,触发主动清理策略

缓存达到最大容量时,redis提供的8种淘汰策略

volatile-lru -> 从已设置过期时间的数据集中选择最久没有使用的数据淘汰
allkeys-lru -> 从数据集中选择最久没有使用的数据淘汰
volatile-lfu -> 从已设置过期时间的数据集中选择最少使用的数据淘汰
allkeys-lfu -> 从数据集中选择最少使用的数据淘汰
volatile-random -> 从已设置过期时间的数据集中随机选择数据淘汰
allkeys-random -> 从数据集中随机选择数据淘汰
volatile-ttl -> 从已设置过期时间的数据集中选择马上就要过期的数据淘汰
noeviction -> 当内存使用超过配置的时候会返回错误,不会驱逐任何键
# LRU 最近最少使用
# LFU 最近最多使用

# 设置最多同时连接的客户端数量。默认这个限制是10000个客户端,然而如果Redis服务器不能配置
# 处理文件的限制数来满足指定的值,那么最大的客户端连接数就被设置成当前文件限制数减32(因为Redis服务器保留了一些文件描述符作为内部使用)
# 一旦达到这个限制,Redis会关闭所有新连接并发送错误'max number of clients reached'
# maxclients 10000
 
# 不要使用比设置的上限更多的内存。一旦内存使用达到上限,Redis会根据选定的回收策略(参见:maxmemmory-policy)删除key。
# maxmemory <bytes>
 
# 最大内存策略:如果达到内存限制了,Redis如何选择删除key。
# volatile-lru -> 根据LRU算法删除设置过期时间的key
# allkeys-lru -> 根据LRU算法删除任何key
# volatile-lfu -> 根据LFU算法删除设置过期时间的key
# allkeys-lfu -> 根据LFU算法删除任何key
# volatile-random -> 随机移除设置过过期时间的key
# allkeys-random -> 随机移除任何key
# volatile-ttl -> 移除即将过期的key(minor TTL)
# noeviction -> 不移除任何key,只返回一个写错误
# 注意:对所有策略来说,如果Redis找不到合适的可以删除的key都会在写操作时返回一个错误。
# 默认策略:
# maxmemory-policy noeviction
 
# LRU和最小TTL算法的实现都不是很精确,但是很接近(为了省内存),所以你可以用样本量做检测。 例如:默认Redis会检查3个key然后取最旧的那个,你可以通过下面的配置指令来设置样本的个数。
# 默认值为5,数字越大结果越精确但是会消耗更多CPU。
# maxmemory-samples 5
 
# replica 节点是否忽略 maxmemory 设置
# replica-ignore-maxmemory yes

redis生产上的教训

  • 一定要进行Master-slave主从同步配置,在出现服务故障时可以切换
  • 物理内存+虚拟内存不足,这个时候dump一直死着,时间久了机器挂掉。这个情况就是灾难!
  • 当Redis物理内存使用超过内存总容量的3/5时就会开始比较危险了,就开始做swap,内存碎片大
  • 当达到最大内存时,会清空带有过期时间的key,即使key未到过期时间。因此要配置合适的maxmemory-policy,即当达到最大内存时的删除策略
  • redis与DB同步写的问题,先写DB,后写redis,因为写内存基本上没有问题。
  • 在master禁用数据持久化,只需要在slave上配置数据持久化 ? 这种方式又会引起另一种问题?
    1. 如果采用RDB,redis在fork一个子进程的时候有可能会引起服务短时间不可用,而采用AOF可能因为持久化和bgrewrite引起
    服务短时间不可用
    2.因此建议在master上不开启RDB和AOF的持久化功能,但是如果这样会引起一个问题,就是在所有服务都关闭后,重启master和slave,此时因为master没有开启持久化,master里没有数据,而slave进行同步的时候会把之前的持久化数据清空覆盖掉。
    3. 解决这种问题的办法就是:在master的配置文件里开启RDB和AOF的持久化功能,而在master启动起来后通过config set save "" 和config set appendonly no 来关闭RDB和AOF的持久化功能,在slave上仍然开启持久化功能
    4.经过上面的解决办法,可以保证数据都在slave上有副本,在master上没有持久化操作不会影响主服务的运行,而当整个master和slave挂掉后,我们只需要将slave的RDB和AOF文件拷贝到master上,并修改文件名为master的RDB和AOF文件名,就可以保证master启动时载入备份数据启动,并且slave启动后也不会造成上面第2条所描述的问题,然后重复第3条操作,就又可以将master设置为不持久配置

redis性能排查,慢查询日志

Redis Slowlog的配置

redis slowlog通过2个参数配置管理,默认命令耗时超过10毫秒,就会被记录到慢查询日志队列中;队列默认保存最近产生的128个慢查询命令。
slowlog-log-slower-than: 慢查询阀值,单位微秒. 默认100000(10毫秒);
生产环境设置1ms,因为Redis是single thread,如果命令都是1ms以上,则实例的吞吐量只有1000QPS.
slowlog-max-len: 慢查询存储的最大个数,默认128;
生产设置设置大于1024,因为slowlog会省略过多的参数,慢查询不会占用过多的内存;
慢查询队列满后,淘汰最老的慢查询实体。

1.2  Redis Slowlog读取

示例:获取最近2个慢查询命令 
127.0.0.1:6381> SLOWLOG get 2

问题

  1. 为什么使用 Redis
  2. 使用 Redis 有什么缺点
  3. Redis为什么说单线程很快?Redis为什么要采用单线程?
    通常使用多线程的场景,是因为磁盘IO操作耗时,造成CPU空闲等待,而不能是CPU发挥最大的性能,因此采用多线程可以使CPU达到充分的使用,而Redis是基于内存的,数据的读写不再是造成性能低下的原因,因此单线程不仅不会使CPU空闲反而会因为单线程的原因避免的线程切换带来的性能开销,因此Redis采用单线程。
  4. Redis 的数据类型,以及每种数据类型的使用场景
  5. Redis 的过期策略以及内存淘汰机制
  6. Redis 和数据库一致性问题
  7. 如何应对缓存穿透和缓存雪崩问题
  8. 如何解决 Redis 的并发竞争 Key 问题
  9. redis脑裂的问题可以通过一下配置来减少数据丢失
    min-replicas-to-write 3 ,Master最少有3个Slave
    min-replicas-max-lag 10,数据复制和同步延迟不能超过10秒
  10. redis集群在什么情况下会不可用?
    有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用。

看这里

Redis,必须会的,我这方便还算懂得多点,可以和面试官大战几个回合吧,应该不至于上来被打趴下,单线程模型,aof,rdb,rewrite,主从,cluster,哪些类型,不要再说常规的5个了,多说几个让你区别其他小哥,包含一些缓存常见的问题击穿、穿透、雪崩、数据一致性等,你必须会,不会基本没戏,一致性hash,布隆过滤器的原理,为此我还去了解了geohash的原理以及google s2的原理,底层数据结构sds和跳表等 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值