缓存

在这里插入图片描述

REDIS简介

  • 完全基于内存,操作效率高
  • 数据结构简单
  • 基于单线程,顺序执行所有请求,避免多线程环境的上下文切换
  • 使用IO多路复用,非阻塞IO

多路IO复用模型

FD(file description) 文件描述符

在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件、目录文件、链接文件和设备文件。文件描述符(file descriptor)是内核为了高效管理已被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符。程序刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。如果此时去打开一个新的文件,它的文件描述符会是3。

BIO(Blocking IO)阻塞IO模型

linux5种IO模型
在这里插入图片描述

select()系统调用

阻塞用户进程,通过轮询的方式监控文件描述符的可读可写状态。将通知任务交由select函数,用户进程可以继续执行其他任务,不被阻塞。

redis采用的多路IO复用函数

epoll/kqueue/evport/select

  • 根据操作系统选择不同函数
  • 优先选择O(1)时间复杂度的函数
  • 使用O(n)时间复杂度的select保底
  • 基于react设计模式监听IO事件

redis基本数据类型

string
hash
list
set
sorted set
hyperloglog
geo

Q:从海量数据里查询某一固定前缀的key

keys pattern: 查找所有符合给定模式pattern的key
使用keys对线上业务的影响

  • 一次返回所有匹配的keys
  • 当key的数量过大会导致服务卡顿

SCAN cursor [MATCH pattern] [COUNT count]:

  • 基于游标的迭代器,需要基于上次查询返回的游标延续之前的迭代行为
  • 以0开始作为一次新的迭代,直到命令返回游标0迭代结束
  • 不保证每次查询返回给定count参数值数量的结果,返回数量不可控
  • 支持以match参数指定的模式模糊查询

Q:如何通过redis实现分布式锁

分布式锁: 控制不同客户端同时访问同一共享数据时所需锁的实现

分布式锁需要解决的问题
  • 互斥性
  • 安全性
  • 容错性
  • 死锁
方式1:setnx + expire

SETNX key value
set not exist 当key不存在时,返回1。否则返回0。
EXPIRE key timeout
给key设置超时时间

int status  = jedis.setnx("lock", "1");
if(status == 1){
	jedis.expire("lock", 1000);
	doSomething();
}

当执行完setnx后宕机,导致没有设置超时时间而一直占用锁

方式2:set

SET key value [EX seconds] [PX milliseconds] [NX|XX]

  • EX 超时时间 单位秒
  • PX 超时时间 单位毫秒
  • NX 当key不存在 执行
  • XX 当key存在 执行
  • 操作成功返回"ok",否则返回"nil"
String status = jedis.set(key, value, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime );
if("OK".equals(status)){
	doSomething();
}
大量key同时过期

集中过期,由于要清除大量过期的key,redis服务可能会出现卡顿
通过使用随机过期时间,使key的过期时间点分散。

Q:如何实现异步队列

方式1:使用list作为队列,rpush生产消息,lpop消费消息

缺点:不会等待队列里有值,直接消费
弥补:在应用层引入循环机制,等待队列里有消息才消费,否则sleep。

方式2:使用blpop key timeout,阻塞控制消费消息

缺点:只能供一个消费者消费

方式3:pub/sub 发布订阅

pub发布者发布消息 PUBLISH channel message
sub订阅者接收消息 SUBSCRIBE channel [channel … ]
订阅者可以订阅任意数量的频道

缺点:消息的发布是无状态的,不保证消息的可达。
在这里插入图片描述

持久化方式之RDB

RDB:保存某个时间点的全量数据快照
SAVE:阻塞redis主进程,直到rdb文件被创建,接收到服务端返回的"ok"。
BGSAVE:服务端立即返回一条消息"Background saving started",并fork出一个子进程来创建rdb文件,不会阻塞主进程继续处理客户端请求。同时主进程通过轮询的方式检查rdb文件是否创建完成。

自动触发RDB持久化的方式
  • 根据redis.conf配置文件中的SAVE m n触发
  • 主从复制时,主节点触发
  • 执行SHUTDOWN,且没有开启AOF时触发
  • 执行DEBUG RELOAD时触发
RDB原理

在这里插入图片描述
redis执行bgsave指令时,会先检查有没有执行aof/rdb的子进程,存在则返回错误调用信息。否则触发持久化操作,调用rdbsavebackground,fork子进程创建一个临时的rdb文件,直到数据持久化完毕,替换之前的rdb文件。在执行fork时,系统使用copy-on-write策略。此过程主进程不会被阻塞,可以执行其他客户端请求。
redis在启动时,发现rdb文件会自动载入。
缺点:
redis内存数据的全量同步,当数据量大时由于IO而影响系统性能
可能由于redis服务器故障而丢失从当前至上次备份期间的数据

copy-on-write

当多个调用者同时请求相同资源时,他们会获得指向相同物理地址的指针。直到其中某个调用者试图修改数据时,系统会为其复制一份副本,而其他调用者所指向的初始资源保持不变。

持久化方式之AOF

  • 记录除了查询操作以外的所有变更数据库状态的操作
  • 以append形式追加到aof文件中(增量保存)
AOF重写原理

在这里插入图片描述

  1. 调用fork生成子进程
  2. 把新的aof写入临时文件,写入操作是基于当前内存数据的状态解析出指令,所以不依赖于原先的aof文件。
  3. 主进程持续将新的变动写入内存和原先的aof文件中,保证数据完整性。
  4. 当主进程获取到子进程重写aof完成信号时,把内存中新的操作追加到新的aof文件中(增量操作)。
  5. 替换原先的aof文件。

BGREWRITEAOF: 手动触发aof重写指令

持久化方式之混合模式

RDB和AOF共存的情况下数据恢复流程

在这里插入图片描述

RDB和AOF的优缺点
  • **RDB优点:**全量数据的快照,文件小,恢复快
  • **RDB缺点:**无法保存最近一次快照后的更新数据
  • **AOF优点:**可读性高,适合保存增量数据,不已丢失
  • **AOF缺点:**文件体积大,恢复时间长。日志回放。
RDB和AOF混合持久化模式

redis 4.0+
BDSAVE全量持久化,AOF增量持久化
redis启动时,使用rdb文件重新构建内容,再通过aof文件重放近期更新指令恢复数据完整状态。

PIPELINE主从同步

pipeline
  1. pipeline和linux的管道相似
  2. redis基于请求响应模式,需要对请求一一应答
  3. pipeline可以批量传输数据,节省多次请求IO时间
  4. 有顺序依赖的指令需要按次序发送
redis的主从同步原理
  1. 首次同步时,主节点调用一次BGSAVE指令保存当前内存的全量数据快照,同时将后续修改操作记录到缓存中。
  2. 当BGSAVE完成后,将rdb文件全量同步到从节点中。接收完成后,将数据加载内存中。
  3. 加载完成后通知主节点,将期间修改的增量数据同步到从节点重放。
全同步过程
  1. slave发送sync指令到master
  2. master启动后台进程,将redis中的数据快照保存到rdb文件 (BGSAVE)
  3. master将保存数据快照期间的修改操作缓存起来
  4. 当master完成rdb文件写入后,将文件发送给slave
  5. 使用心得rdb文件替换原先的rdb文件,并将全量数据载入内存。
  6. 完成数据载入后,通知master发送此期间新增的修改命令并重放。
    全量同步完成之后,所有写操作都是在master上进行,所有读操作都是在slave上进行。
增量同步过程

为保证redis主从在运行期间数据的最终一致性,需要把master上的写操作扩散到slave中。

  1. master接收到指令,处理并判断是否需要扩散到slava中
  2. 将操作记录追加到aof文件中
  3. 将操作传播到其他slave中: a.对其主从库。b.将操作写入响应缓存中。
  4. 将缓存中的数据发送给slave

主从模式缺点:不具备高可用性。当主服务器挂掉后就不能对外提供新的写入操作。因此会选择使用哨兵模式(sentinel)保证redis集群的高可用性

redia哨兵模式

sentinel功能
  • 监控:检查主从服务器运行状态 (留言协议)
  • 提醒:通过api向管理员发送故障通知
  • 自动故障迁移:主从切换 (投票协议)
留言协议 gossip

在这里插入图片描述

集群

如何从海量数据中快速找到所需
  • 分片:按照某种规则划分数据,分散存储在多个节点中
  • 常规的按照哈希划分无法实现节点的动态增减
一致性哈希算法

在这里插入图片描述

  1. 对redis服务器的ip地址或者主机名进行哈希后,对2^32取模,计算redis服务器在哈希环上的位置
  2. 对数据的key同样进行哈希取模后,获取到数据的存放位置。
  3. 数据沿顺时针遇到的第一个redis服务器节点保存次数据。

Node C宕机
在这里插入图片描述

新增Node X
在这里插入图片描述

hash环的数据倾斜
在这里插入图片描述

引入虚拟节点解决数据倾斜问题
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值