写点什么

Redis- 用的很溜,了解过它用的什么协议吗?,3 天拿到网易 Java 岗 offer

用户头像
极客good
关注
发布于: 刚刚

4、子进程开始进行持久化工作,对现有数据进行完整的快照存储;


5、子进程完成操作后,通知父进程;


RDB 的优点:

  • RDB 是一个紧凑压缩的二进制文件,代表 Redis 在某个时间点上的数据 快照。非常适用于备份,全量复制等场景。比如每 6 小时执行 bgsave 备份, 并把 RDB 文件拷贝到远程机器或者文件系统中(如 hdfs),用于灾难恢复。

  • Redis 加载 RDB 恢复数据远远快于 AOF 的方式。

RDB 的缺点:

  • RDB 方式数据没办法做到实时持久化/秒级持久化。因为 bgsave 每次运 行都要执行 fork 操作创建子进程,属于重量级操作,频繁执行成本过高。

  • RDB 文件使用特定二进制格式保存,Redis 版本演进过程中有多个格式 的 RDB 版本,存在老版本 Redis 服务无法兼容新版 RDB 格式的问题。

AOF 方式

AOF 由下面几个参数控制。

appendonly 参数开启 AOF 持久化

appendonly yes

AOF 持久化的文件名,默认是 appendonly.aof

appendfilename "appendonly.aof"

AOF 文件的保存位置和 RDB 文件的位置相同,都是通过 dir 参数设置的

dir ./

同步策略

appendfsync always

appendfsync everysec

appendfsync no

aof 重写期间是否同步

no-appendfsync-on-rewrite no

重写触发配置

auto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb

加载 aof 出错如何处理

aof-load-truncated yes

文件重写策略

aof-rewrite-incremental-fsync yes


针对 RDB 不适合实时持久化的问题,Redis 提供了 AOF 持久化方式来解决,AOF 也是目前最流程的持久化方式。


AOF(append only file),以独立日志的方式记录每次写命令, 重启时再重新执行 AOF 文件中的命令达到恢复数据的目的。


1、所有的写入命令会追加到 aof_buf(缓冲区)中;


2、AOF 缓冲区根据对应的策略向硬盘做同步操作;


3、随着 AOF 文件越来越大,需要定期对 AOF 文件进行重写,达到压缩的目的;


4、当 Redis 服务器重启时,可以加载 AOF 文件进行数据恢复;


AOF 文件里存的是什么

我在本地的测试 redis 环境中随便刷了几条命令,然后打开 appendonly.aof 文件查看,发现里面的内容像下面这样子。


RESP 协议

Redis 客户端与服务端通信,使用 RESP 协议通信,该协议是专门为 Redis 设计的通信协议,但也可以用于其它客户端-服务器通信的场景。


RESP 协议有如下几个特点:


  • 实现简单;

  • 快速解析;

  • 可阅读;


客户端发送命令给服务端,服务端拿到命令后进行解析,然后执行对应的逻辑,之后返回给客户端,当然了,这一发一回复都是用的 RESP 协议特点的格式。


一般情况下我们会使用?redis-cli或者一些客户端工具连接 Redis 服务端。


./redis-cli


然后整个交互


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


过程的命令发送和返回结果像下面这样,绿色部分为发送的命令,红色部分为返回的结果。



这就是我们再熟悉不过的部分了。但是,这并不能看出 RESP 协议的真实面貌。

用 telnet 试试

RESP 是基于 TCP 协议实现的,所以除了用各种客户端工具以及 Redis 提供的?redis-cli工具,还可以用 telnet 查看,用 telnet 就可以看出 RESP 返回的原始数据格式了。


我本地的 Redis 是用的默认 6379 端口,并且没有设置 requirepass ,我们来试一下用 telnet 连接。


telnet 127.0.0.1 6379


然后执行与前面相同的几条命令,发送和返回的结果如下,绿色部分为发送的命令,红色为返回的结果。



怎么样,有些命令的返回还好,但是像get str:hello这条,返回的结果除了?world值本身,上面还多了一行?$5,是不是有点迷糊了。

协议规则

请求命令

一条客户端发往服务器的命令的规则如下:


*<参数数量> CR LF<参数 N 的字节数量> CR LF<参数 N 的数据> CR LF


RESP 用\r\n作为分隔符,会表明此条命令的具体参数个数,在命令上看来,空格分隔的都表示一个参数,例如?set str:hello world?这条命令就是 3 个参数,会表明每个参数的字符数和具体内容。


用这条命令举例,对应到 RESP 协议规则上就会变成下面这个样子:


*3\r\n3\r\nset\r\n9str:hello\r\n$5world\r\n


服务端回复

Redis 命令会返回多种不同类型的回复。


通过检查服务器发回数据的第一个字节, 可以确定这个回复是什么类型:


1、状态回复(status reply)的第一个字节是?"+"


比如?ping命令的回复,+PONG\r\n


2、错误回复(error reply)的第一个字节是?"-"


比如输入一个 redis 中不存在的命令,或者给某些命令设置错误的参数,例如输入?auth,auth 命令后面需要有一个密码参数的,如果不输入就会返回错误回复类型。


-ERR wrong number of arguments for 'auth' command\r\n


3、整数回复(integer reply)的第一个字节是?":"


例如?INCRDECR?自增自减命令,返回的结果是这样的?:2\r\n


4、批量回复(bulk reply)的第一个字节是?"$"


例如对 string 类型执行 get 操作,$5\r\nworld\r\n$后面的数字 5 表示返回的结果有 5 个字符,后面是返回结果的实际内容。


5、多条批量回复(multi bulk reply)的第一个字节是?"*"


例如?LRANGE key start stop或者?hgetall等返回多条结果的命令,比如?lrange命令返回的结果:

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
Redis-用的很溜,了解过它用的什么协议吗?,3天拿到网易Java岗offer