Redis_高级

发布时间 2023-12-23 15:31:08作者: Espre-sso

Redis_高级

分布式缓存

单点Redis的问题:

  • 数据丢失问题:实现Redis数据持久化
  • 并发能力问题:搭建主从集群,实现读写分离
  • 故障恢复问题:利用Redis哨兵,实现健康检测和自动恢复
  • 存储能力问题:搭建分片集群,利用插槽机制实现动态扩容

数据丢失问题-数据持久化

  1. RDB
    基本流程
  • fork主进程获得一个子进程,共享内存空间
  • 子进程读取内存数据并写入新的RDB文件
  • 用新的RDB文件替换旧的RDB文件
    什么时候执行,save 60 1000什么含义
    • 默认是服务停止时
  • 代表60秒内至少执行1000次修改则触发RDB
    RDB的缺点:
  • RDB执行间隔时间长,两次RDB之间写入数据有丢失的风险。
  • fork子进程、压缩、写出RDB文件都比较耗时。
  1. AOF
    AOF默认是关闭的,需要修改redis.conf配置文件来开启AOF,也可以设置记录的频率(always同步刷盘,everysec每秒刷盘,no操作系统控制)

RDB对比AOF

  • 持久化方式:定时对整个内存做快照---记录每一次执行的命令
  • 数据完整性:不完整,两次备份之间会丢失---相对完整,取决于刷盘策略
  • 文件大小:会有压缩,文件体积小---记录命令,文件体积很大
  • 宕机恢复速度:很快---慢
  • 数据恢复优先级:低,因为数据完整性不如AOF---高,因为数据完整性更高
  • 系统资源占用:高,大量CPU和内存消耗---低,主要是磁盘IO资源,但AOF重写时会占用大量CPU和内存资源。
  • 使用场景:可以容忍数分钟的数据丢失,追求更快的启动速度---对数据安全性要求较高

并发能力-主从架构

搭建主从架构:
单节点redis的并发能力是有上限的,要进一步提高redis的并发能力,就需要搭建主从集群,实现读写分离。

数据同步原理:

  1. 全量同步
    主从第一次同步是全量同步。主-RDB->从
    如何判断slave是否是第一次来同步数据:
  • Replication Id:简称replid,是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid。(判断是否属于同一个主从集群)
  • offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset洗哦啊雨master的offset,说明slave数据落后于master,需要更新。

因此slave做数据同步,必须向master声明自己的replivation id 和offset,master才可以判断到底需要同步哪些数据

简述全量同步的流程

  • slave节点请求增量同步
  • master节点判断replid,发现不一致,拒绝增量同步
  • master将完整内存数据生成RDB,发送RDB到slave
  • slave清空本地数据,加载master的RDB
  • master将RDB期间的命令记录在repl_baklog,并持续将log中的命令发送给slave
  • slave执行接收到的命令,保持与master之间的同步
  1. 增量同步
    主从第一次同步是全量同步,但如果slave重启后同步,则执行增量同步。

注意:repl_baklog大小有上限,写满后会覆盖最早的数据。如果slave断开时间过久,导致数据被覆盖,则无法实现增量同步,只能再次全量同步。

可以从以下几个方面优化redis主从集群

  • 在mater中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO
  • redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO
  • 适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步。
  • 限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力。

总结:
简化全量同步和增量同步区别

  • 全量同步:master将完整内存数据生成RDB,发送RDB到slave,后续命令则记录在repl_baklog,逐个发送给slave
  • 增量同步:slave提交自己的offset给master,master获取repl_baklog中从offset子后的命令给slave

什么时候执行全量同步

  • slave节点第一次连接master节点时
  • slave节点断开时间太久,repl_baklog中的offset已经被覆盖时

什么时候执行增量同步

  • slave节点断开又恢复,并且在repl_baklog中能找到offset时。

故障恢复-哨兵机制

sentinel的3个作用是什么

  • 监控
  • 故障转移
  • 通知

sentinel如何判断一个redis实例是否健康

  • 每隔1s发送一次ping命令,如果超过一定时间没有响应则认为是主观下线。
  • 如果大多数sentinel都认为实例主观下线,则判定服务下线。

故障转移步骤有哪些

  • 首先选定一个slave作为新的master
  • 然后让所有节点都执行slaveof 新master
  • 修改故障节点配置,添加slaveof 新master

存储能力-分片集群

主从&哨兵解决高可用、高并发问题,但仍有2个问题没有解决:

  • 海量数据存储问题
  • 高并发写的问题

使用分片集群可以解决上述问题,分片集群特征:

  • 集群中有多个master,每个master保存不同数据
  • 每个master都可以有多个slave节点
  • master之间通过ping监测彼此健康状态
  • 客户端请求可以访问集群任意节点,最终都会被转发到正确节点

散列插槽
redis会把每一个master节点映射到0~16383共16384个插槽(hash slot)上。
数据key不是与节点绑定,而是与插槽绑定。redis会根据key的有效部分计算插槽值,分2种情况:

  • key中包含{},且{}中至少包含1个字符,{}中的部分是有效部分
  • key中不包含{},整个key都是有效部分

计算方式:
利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是slot值。

redis如何判断某个key应该在哪个实例

  • 将16384个插槽分配到不同的实例
  • 根据key的有效部分计算哈希值,对16384取余
  • 余数作为插槽,寻找插槽所在实例即可

如何将同一类数据固定的保存在同一个redis实例

  • 这一类数据使用相同的有效部分,例如key都以{typeid}为前缀

集群伸缩:
增加or减少节点

故障转移
当集群中有一个master宕机会发生什么:

  1. 首先是该实例与其它实例失去连接
  2. 然后是疑似宕机
  3. 最后是确认下线,自动提升一个slave为新的master

数据迁移
利用cluster failover命令可以手动让集群中的某个master宕机,切换到执行cluster failover命令的这个slave节点,实现无感知的数据迁移。其流程如下:

  1. slave节点告诉master节点拒绝任何客户端请求
  2. master返回当前的数据offset给slave
  3. 等待该slave数据offset与master一致
  4. 开始故障转移
  5. 该slave标记自己为master,广播故障转移的结果
  6. master收到广播,开始处理客户端读请求

多级缓存

传统缓存的问题:
传统的缓存策略一般是请求到达Tomcat后,先查询redis,如果未命中则查询数据库,存在以下问题:

  • 请求要经过tomcat处理,tomcat的性能成为整个系统的瓶颈
  • redis缓存失效时,会对数据库产生冲击

多级缓存方案:
用作缓存的nginx是业务nginx,需要部署为集群,再有专门的nginx用来做反向代理: