简介

Redis是一个高性能的NoSQL数据库,采用key-value结构存储数据到内存中,通过磁盘文件进行持久化。value的存储结构有string、list、set、sorted set、hash。
官方提供redis.conf下载

五种数据类型

string

以字符串形式保存value值。

list

以数组形式保存value值,特点是有序。

set

以无序集合的形式保存value,特点是无序、去重。

sorted set

以有序集合的形式保存value,特点是有序、去重。

hash

以键值对的形式保存value,值value是一个hash表。

Redis为什么快

数据结构简单

Redis中的数据都是hash表,以key-value的形式存储,读写的时间复杂度是O(1)。

内存操作

Redis的所有数据都存在内存当中,避免了磁盘的IO操作,内存读写的性能远高于磁盘的读写性能。

单线程

目前所说的Redis单线程,指的是”其网络IO和键值对读写是由一个线程完成的”。所以对键值的读写是单线程完成的,不存在线程之间的资源竞争和上下文切换。

多路复用

单线程也能并发处理多客户端的请求,因为使用了基于epoll的多路复用。一个线程监听多个客户端,避免了IO等待导致的阻塞操作,省去了线程切换带来的开销。

4.0引入了异步删除

因为是单线程处理键值,所以当删除一个非常大的对象时,主线程会阻塞其它的指令执行。而4.0引入的异步删除(unlink key)就可以有效避免这个情况,它采取子线程删除的方式执行删除操作。

6.0多线程IO

虽然采用了多路复用,但IO数据传输的过程本身是阻塞的。通过多线程IO进一步优化性能,官方测试结果表明通过多线程IO特性能对性能提升至少一倍以上。
默认是禁用多线程的,通过配置项开启多线程IO(io-threads-do-reads=true)以及设置线程数(io-threads=4 ),官方的建议是如果为4核CPU,那么设置线程数为2或3;如果为8核CPU,那么设置线程数为6.总之线程数一定要小于机器的CPU核数,线程数并不是越大越好(因为线程数超过核心数,那么线程就会频繁的切换上下文造成开销)。

持久化方式

RDB(默认)

RDB快照方式(RDB, Redis DataBase),把当前Redis进程中的所有数据以快照的形式保存到磁盘文件。
触发RDB持久化方式有两种:

  • 手动触发
    • save指令,是同步执行,save会直接在主线程进行持久化,期间Redis阻塞,无法对外提供服务。
    • bgsave指令,是异步执行,fork一个子进程,然后在进程中进行持久化,不阻塞Redis对外服务。
  • 自动触发
    • serverCron定时执行。
    • 主节点向子节点发出bgsave。
    • 执行指令debug reload会自动执行save指令,并重新加载rdb文件。
    • shutdown时会自动执行bgsave。

image.png
RDB持久化的优缺点:

  • RDB优点
    • RDB是一个紧凑压缩的二进制文件,占用磁盘空间小,RDB文件代表Redis在某一个时间点上的数据快照,非常适合用于备份、全量复制等场景。
    • RDB对灾难恢复、数据迁移非常友好,RDB文件可以转移至任何需要的地方并重新加载。
    • RDB是Redis数据的内存快照,数据恢复速度较快,相比于AOF的命令重放有着更高的性能。
  • RDB缺点

    • RDB方式无法做到实时或秒级持久化。因为持久化过程是通过fork子进程后由子进程完成的,子进程的内存只是在fork操作那一时刻父进程的数据快照,而fork操作后父进程持续对外服务,内部数据时刻变更,子进程的数据不再更新,两者始终存在差异,所以无法做到实时性。
    • RDB持久化过程中的fork操作,会导致内存占用加倍,而且父进程数据越多,fork过程越长。
    • Redis请求高并发可能会频繁命中save规则,导致fork操作及持久化备份的频率不可控;
    • RDB文件有文件格式要求,不同版本的Redis会对文件格式进行调整,存在老版本无法兼容新版本的问题。

      AOF

      文件追加方式(AOF, Append Only File),记录所有的操作命令,并以文本的形式追加到文件中;RDB由于工作原理的“先天性缺陷”无法保证实时性持久化,这对于缓存丢失零容忍的系统来说是个硬伤,于是就有了AOF。
      AOF是先执行命令,再追加到磁盘文件中。
      AOF持久化模式默认是关闭的,修改redis.conf以下信息并重启,即可开启AOF持久化功能。
      1. # no-关闭,yes-开启,默认no
      2. appendonly yes
      3. appendfilename appendonly.aof
      AOF优点
  • 具有更好的实时性,提供三种追加方式(appendfsync):no、every second、always。默认为every second策略(具有最好的性能,极端情况下可能会丢失一秒的数据)。

  • 只有append操作,无复杂的seek等文件操作,没有损坏风险。即使最后写入数据被截断,也很容易使用redis-check-aof工具修复。
  • 当AOF文件变大时,Redis可在后台自动重写。重写过程中旧文件会持续写入,重写完成后新文件将变得更小,并且重写过程中的增量命令也会append到新文件。
  • AOF文件以易理解与解析的方式包含了对Redis中数据的所有操作命令。即使不小心错误的清除了所有数据,只要没有对AOF文件重写,我们就可以通过移除最后一条命令找回所有数据。
  • AOF已经支持混合持久化,文件大小可以有效控制,并提高了数据加载时的效率。

AOF缺点

  • 对于相同的数据集合,AOF文件通常会比RDB文件大。
  • 在特定的fsync策略下,AOF会比RDB略慢。一般来讲,fsync_every_second的性能仍然很高,fsync_no的性能与RDB相当。但是在巨大的写压力下,RDB更能提供最大的低延时保障。
  • 在AOF上,Redis曾经遇到一些几乎不可能在RDB上遇到的罕见bug。一些特殊的指令(如BRPOPLPUSH)导致重新加载的数据与持久化之前不一致,Redis官方曾经在相同的条件下进行测试,但是无法复现问题。

    混合持久化

    RDB和AOF持久化各有优缺点,RDB会导致一段时间内的数据丢失,AOF文件会越来越大,会影响Redis的启动速度,为了同时兼顾RDB,AOF的优点,Redis在4.0版本之后提供了混合持久化方式。
    AOF 重写时会把 Redis 的持久化数据,以 RDB 的格式写入到 AOF 文件的开头,之后的数据再以 AOF 的格式化追加的文件的末尾。开启混合持久化模式需修改配置文件。
    使用混合持久化的时候可以根据自身业务选择关闭RDB或者AOF,或者关闭持久化。
    Redis4.0是默认关闭混合模式的,而5.0开始是默认开启混合模式,但aof始终是默认关闭,需要开启aof才能使用混合模式。

    1. # no-关闭,yes-开启,4.0默认no,5.0之后默认yes
    2. aof-use-rdb-preamble yes

    混合持久化优缺点:

  • 优点

    • 混合持久化结合了 RDB 和 AOF 持久化的优点,开头为 RDB 的格式,使得 Redis 可以更快的启动。
    • 结合了 AOF 的优点,降低数据丢失的风险。
  • 缺点
    • AOF 文件中添加了 RDB 格式的内容,会使得 AOF 文件的可读性会很差,不容易阅读。
    • 如果开启混合持久化,就必须使用Redis 4.0 以及之后版本。

      数据加载流程

      Redis启动时,需要将持久化到文件中的数据恢复到内存中,根据配置的持久化方式选择加载AOF文件或者RDB文件。
      image.png

      缓存淘汰策略

      缓存淘汰策略是Redis内部对缓存数据进行清理的策略,若不进行缓存数据清理,那么缓存数据会无限增长导致内存不足。
      Redis4.0开始提供了8种淘汰策略:
不删除 noeviction 默认策略,不淘汰数据;大部分写命令都将返回错误(DEL等少数除外)
Random allkeys-random 从所有数据中随机挑选数据淘汰
Random volatile-random 从设置了过期时间的数据中随机挑选数据淘汰
LRU allkeys-lru 从所有数据中根据 LRU 算法挑选数据淘汰
LRU volatile-lru 从设置了过期时间的数据中根据 LRU 算法挑选数据淘汰
LFU allkeys-lfu 从所有数据中根据 LFU 算法挑选数据淘汰(4.0及以上版本可用)
LFU volatile-lfu 从设置了过期时间的数据中根据 LFU 算法挑选数据淘汰(4.0及以上版本可用)
最短存活时间 volatile-ttl 从设置了过期时间的数据中,挑选越早过期的数据进行删除

Redis基础 - 图3

参考文献

关于Redis 三种持久化,你需要了解的事儿?
Redis专题:万字长文详解持久化原理
Redis缓存淘汰策略?
玩转Redis-8种数据淘汰策略及近似LRU、LFU原理