Redis基础:
Redis为什么快
- 基于内存,内存访问速度比磁盘快
- 基于Reactor 模式设计开发单线程事件模型和io多路复用
- 内置了多种优化的数据类型
- 通信协议实现简单且解析高效
Redis基本数据类型
String
-
需要存储常规数据的场景:缓存 Session、Token、图片地址、序列化后的对象(相比较于 Hash 存储更节省内存)。
-
需要计数的场景:用户单位时间的请求数(简单限流可以用到)、页面单位时间的访问数。
-
分布式锁:
SETNX key value
List
List 实现为一个双向链表
Hash
Hash 是一个 String 类型的 field-value(键值对) 的映射表,特别适合用于存储对象
Set
Set 类型是一种无序集合,集合中的元素没有先后顺序但都唯一
- 需要获取多个数据源交集、并集和差集的场景
- 需要随机获取数据源中的元素的场景
Sorted Set
和 Set 相比,Sorted Set 增加了一个权重参数 score
,使得集合中的元素能够按 score
进行有序排列
Redis持久化
使用缓存的时候,我们经常需要对内存中的数据进行持久化也就是将内存中的数据写入到硬盘中。
Redis支持三种持久化方式
- RDB:快照
- AOF:只追加文件
- RDB和AOF的混合持久化
RDB持久化:
Redis可以通过创建快照来获得在内存里面的数据在某个时间点上的副本。
Redis提供了两个命令生成RDB快照
save
:同步保存,会阻塞主线程bgsave
:fork出一个子进程,子进程执行,不会阻塞Redis主线程。
AOF持久化
什么是AOF持久化
AOF持久化的实时性更好
开启AOF持久化后,每执行一条会更改Redis中的数据的命令,Redis就会将命令写入AOF缓冲区,然后再写入到AOF文件中,最后再根据持久化方式的配置决定何时同步到硬盘中。
AOF的工作流程
- 命令追加:将所有的写命令追加到AOF缓冲区。
- 文件写入:将AOF缓冲区的数据写入AOF文件。需要调用
write
函数,将数据写入系统内核缓冲区之后直接返回。 - 文件同步:根据对应的持久化方式向硬盘做同步操作。这一步调用
fsync
函数,强制刷新系统内核缓冲区,同步到硬盘。 - 文件重写:随着AOF文件越来越大,需要定期对AOF文件进行重写,达到压缩的目的。
- 重启加载:当Redis重启时,可以加载AOF文件进行数据恢复。
持久化方式是什么?有哪些?
AOF持久化方式是指,系统调用fsync
函数的策略。
-
appendfsync always
:主线程调用write
执行写操作后,后台线程(aof_fsync
线程)立即会调用fsync
函数同步 AOF 文件(刷盘),fsync
完成后线程返回,这样会严重降低 Redis 的性能(write
+fsync
)。 -
appendfsync everysec
:主线程调用write
执行写操作后立即返回,由后台线程(aof_fsync
线程)每秒钟调用fsync
函数(系统调用)同步一次 AOF 文件(write
+fsync
,fsync
间隔为 1 秒) -
appendfsync no
:主线程调用write
执行写操作后立即返回,让操作系统决定何时进行同步,Linux 下一般为 30 秒一次(write
但不fsync
,fsync
的时机由操作系统决定)。
AOF在执行写命令后记录日志
关系型数据与Redis之所以不同,主要由于他们的设计目标和适用场景的差异
mysql在执行命令之前记录日志是因为:注重数据的完整性和一致性,虽然增加了写入操作的开销,但保证了数据的完整性和一致性,也方便了故障恢复到一致的状态。
Redis是在执行命令之后记录日志,要求最大限度提高性能,保证了高性能和低延时的特点。
好处
- 避免额外的检查开销,AOF记录日志不会对命令进行语法检查
- 在命令执行之后再记录日志,不会阻塞当前命令执行。
不足
- 如果刚执行完命令发生宕机,会导致对应的修改丢失
- 可能会阻塞后续其他命令的执行
AOF重写
工作流程
- 创建快照
AOF会创建当前数据集的一个数据快照,并以最小的命令集合重写所有数据。也就是说,它能根据当前数据库状态生成能够重建当前数据的最小集合命令。
- 写入新文件
Redis将新生成的命令集合写入新的AOF文件,这样极大的缩减了文件的大小。
- 原子替换:
- 在重写过程中,Redis继续将新的写操作追加到现有AOF文件和新AOF文件中,确保在重写阶段数据不丢失。
- 重写完成后,用新的AOF文件代替旧AOF文件,这一操作是原子的,确保数据不丢失。完成重写