简介
Redis是一个高性能的NoSQL数据库,采用key-value结构存储数据到内存中,通过磁盘文件进行持久化。value的存储结构有string、list、set、sorted set、hash。
官方提供redis.conf下载
五种数据类型
string
list
set
sorted set
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。
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持久化功能。
AOF优点# no-关闭,yes-开启,默认no
appendonly yes
appendfilename appendonly.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才能使用混合模式。# no-关闭,yes-开启,4.0默认no,5.0之后默认yes
aof-use-rdb-preamble yes
混合持久化优缺点:
优点
- 混合持久化结合了 RDB 和 AOF 持久化的优点,开头为 RDB 的格式,使得 Redis 可以更快的启动。
- 结合了 AOF 的优点,降低数据丢失的风险。
- 缺点
不删除 | 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 三种持久化,你需要了解的事儿?
Redis专题:万字长文详解持久化原理
Redis缓存淘汰策略?
玩转Redis-8种数据淘汰策略及近似LRU、LFU原理