面试八股文之Redis

Redis基本设计

Redis的五种类型数据结构

类型

数据结构

数据结构间转化条件

备注

string

int

整数值

embstr

字符串(长度<=39byte)

y?底层都是SDS(simple dynamic string,简单动态字符串)实现,但raw需要分配两次内存(redisObject和sdshdr),embstr只需要一次

raw

字符串(长度>39byte)

list

ziplist

压缩列表:每个字符串元素的长度<64byte且元素数量<512

linkedlist

双端列表:不满足压缩列表条件,则使用双端列表

hash

ziplist

压缩列表:所有键值对的字符串长度<64byte且键值对数量<512

hashtable

字典:不满足压缩列表条件,则使用字典

set

intset

整数集合:所有元素都是整数值且元素数量<512

hashtable

字典:不满足整数集合条件,则使用字典

zset

ziplist

压缩列表:所有元素长度<64byte且元素数量<128

skiplist+

hashtable

跳跃表+字典:不满足压缩列表条件,则使用跳跃表+字典

字典详解

Redis字典

客户端与Redis服务器的一次通信过程

redis6.0之后开始引入多线程,可选择性使用多线程模型,Redis的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程。

Redis选择使用单线程模型处理客户端的请求主要还是因为CPU不是Redis服务器瓶颈,所以使用多线程模型带来的性能提升并不能抵消他带俩的开发成本和维护成本,系统的性能瓶颈主要在网络I/O操作上;而Redis引入多线程操作也是出于性能考虑,对于一些大键值对的删除操作,通过多线程非阻塞地释放内存空间也能减少对Redis主线程阻塞的时间,提高执行效率。

过期策略与淘汰策略

过期策略

实现方式

备注

惰性删除策略

所有读写操作,在执行前都会调用expireIfNeeded函数对键进行检查,过滤掉已过期的键,避免命令接触到过期键。

两种策略相互配合,在合理使用CPU时间和避免浪费内存空间之间取得平衡.

定期删除策略

周期性执行redis.c/serverCron,每次运行都从一定数据量的数据库中取出一定数量的随机减进行检查,并删除其中的过期键

淘汰策略

实现方式

备注

noeviction(默认策略)

不删除策略。达到最大内存限制时,如果需要更多内存,直接返回错误信息。

allkeys-lru

所有key通用,优先删除最近最少使用(LRU:less recently used)的key。适用场景:数据分热数据与冷数据。最常用的。

volatile-lru

只限于设置了expire的部分,优先删除最近最少使用的key。

allkeys-random

所有key通用,随机删除一部分key。适用场景:所有元素的概率差不多。

volatile-random

只限于设置了expire的部分,随机删除一部分key。

volatile-ttl

只限于设置了expire的部分,优先删除剩余时间(TTL:time to live)短的key。

volatile-lfu

LFU (Least frequently used) 最不经常使用,如果一个数据在最近一段时间内使用次数很少,那么在将来一段时间内被使用的可能性也很小。

redis4.0

allkeys-lfu

如果定期删除漏掉了很多过期key,这些key也没有及时去查,也就没走惰性删除,大量key堆积在内存,导致redis内存快耗尽了,这种情况会走上面的淘汰策略。

持久化

类型

触发条件

存储方式

载入方式

对过期键的处理

使用场景(优缺点)

备注

RDB

Save 900 1

服务器900s之内,对数据库进行了至少1次修改

Save 300 10

服务器300s之内,对数据库进行了至少10次修改

Save 60 10000

服务器60s之内,对数据库进行了至少10000次修改

可以简单理解为将某时刻的数据按固定的数据结构存储下来

解析数据结构,还原当时数据库状态

存储的是数据结构,存储/载入时,忽略过期键

AOF与RDB同时开启情况下,会优先使用AOF,因为AOF更新频率高。

只有在AOF没有开启的情况下,才会使用RDB来还原数据库状态。

(RDB-AOF混合持久化格式-reidis4.0)

AOF

always:服务器在每次事件循环都将aof_buf缓冲区中的所有内容写入到AOF文件,并且同步AOF文件

everysc:服务器在每次事件循环都将aof_buf缓冲区中的所有内容写入到AOF文件,并且每隔一秒子线程同步AOF

no:服务器在每次事件循环都将aof_buf缓冲区中的所有内容写入到AOF文件,同步时机由操作系统控制

通过记录所有执行的写命令

(顺序写,效率很高)

将命令重新执行一遍

存储时,无影响;

载入时,显式追加删除过期键的del命令

AOF重写机制

主从同步

类型

实现方式

图示

适用场景

备注

完整重同步

SLAVE -> MASTER : 发送SYNC命令

MASTER -> SLAVE :发送RDB文件

MASTER -> SLAVE :发送缓存区所有写命令

1、从服务器初始化

2、服务器断线时间较长的重连场景

非常耗资源

1、生成RDB文件,耗费主服务器大量CPU、内存、磁盘I/O资源

2、接受RDB文件,处理RDB文件,无法处理命令请求

部分重同步

MASTER -> SLAVE :同步数据时,同时同步复制偏移量

SLAVE -> MASTER :将从服务器的复制偏移量,传给主服务器

MASTER -> SLAVE : 将复制偏移量往后的数据,传给从服务器(复制偏移量仍然在复制积压缓冲区中-默认1MB,否则执行完整重同步)

1、主从同步

2、服务器断线重连

脑裂(min-slaves-to-write 2、min-slaves-max-lag 5)

Redis集群

集群通信协议

Redis集群通信采用Gossip协议,简单讲:各个服务器平等关系无主从,集群节点信息变更会不断地发送给其他节点。

优点:元数据信息分散,更新压力小

缺点:更新延迟

meet

某个节点发送meet给新加入的节点,让新节点加入集群中,然后新节点就会开始与其他节点进行通信。

ping

每个节点都会频繁给其他节点发送ping,其中包含自己的状态还有自己维护的集群元数据,互相通过ping交换元数据。

pong

返回ping和meet,包含自己的状态和其他信息,也用于信息广播和更新。

fail

某个节点判断另一个节点fail之后,就发送fail给其他节点,通知其他节点说:某个节点宕机了。

其他通信协议,如: 集中式(zookeeper)

分布式寻址

Redis采用hash slot算法:

  1. 16384个hash slot,对每个key计算CRC16值,然后对16384取模,可以获取key对应的hash slot。

  2. 比如3个master,每个持有5000多个hash slot,任何一台机器宕机,另外两个节点不受影响,因为key找的是hash slot,不是机器。

  3. 客户端api可以对指定的数据,让他们走同一个hash slot,通过 hash tag 来实现。

其他寻址方式,如:hash算法、一致性hash算法

故障检测与转移

检测:

集群中的每个节点都会定期地向集群中其他节点发送ping消息,来检测对方是否在线,如果接受ping消息的节点没有在规定时间内返回pong消息,则该接受ping消息的节点标记为疑似下线pfail。

如果在一个集群中,半数以上负责处理槽的主节点都将某个主节点x标记为疑似下限,那么这个主节点x将被标记为已下线,将主节点x标记为已下线的节点会向集群广播一条关于主节点x的fail消息,所有收到这条fail消息的节点都会立即将主节点x标记为已下线。

转移:

  1. 复制下线主节点的所有从节点里面,会有一个从节点被选中。

  2. 被选中的从节点会执行SLAVE OF no one命令,成为新的主节点。

  3. 新的主节点会撤销所有对已下线的主节点的槽指派,并将这些槽全部指派给自己。

  4. 新的主节点向集群广播一条PONG消息,这条PONG消息可以让集群中的其他节点立即知道这个节点已经由从节点变成了主节点,并且这个主节点已经接管了原本由已下线节点负责处理的槽。

  5. 新的主节点开始接收和自己负责处理的槽有关的命令请求,故障转移完成。

      主节点选举(Raft领头选举算法):
  6. 集群的配置纪元是一个自增计数器,它的初始值为0。

  7. 当集群里的某个节点开始一次故障转移操作时,集群配置纪元的值会被+1。

  8. 对于每个配置纪元,集群里每个负责处理槽的主节点都有一次投票的机会,而第一个向主节点要求投票的从节点将获得主节点投票。

  9. 当从节点发现自己正在复制的主节点进入已下线状态时,从节点会向集群广播一条CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST消息,要求所有收到这条消息、并且有投票权的主节点向这个从节点投票。

  10. 如果一个主节点具有投票权(它正在负责处理槽),并且这个主节点尚未投票给其他的从节点,那么主节点将向要求投票的从节点返回一条CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK消息,表示这个主节点支持从节点成为新的主节点。

  11. 每个参与选举的从节点都会接收CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK消息,并根据自己收到了多少条这种消息来统计自己获得了多少主节点的支持。

  12. 如果集群里有N个具有投票权的主节点,那么当一个从节点收集到大于等于N/2+1张支持票时,这个节点就会当选为新的主节点。

  13. 因为在每一个配置纪元里面,每个具有投票权的主节点只能投一次票,所以如果有N个主节点进行投票,那么具有大于等于N/2+1张支持票的从节点只会有一个,这确保了新的主节点只会有一个。

  14. 如果在一个配置纪元里面没有从节点能收集到足够多的支持票,那么集群进入一个新的配置纪元,并再次进行选举,直到选出新的主节点为止。

      从节点选举成主节点优先级
    1. 复制时间靠前

    2. offset越大

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值