简介
Redis 是一个完全开源免费的,用 C 语言编写的,一个单线程的,高性能的(key / value)内存数据库,基于内存运行并支持持久化的 NoSQL 数据库
主要用来做缓存,但是不仅仅是缓存,还能利用计数器做分布式唯一主键,分布式锁,队列,会话缓存等

五大数据类型
- string
是 Redis 的基本类型,string 类型是二进制安全的,可以包含任何数据,可以是图片或序列化的对象,最多存储 512 M
- list
Reids 列表是简单的字符串列表,按照插入顺序排列,你可以添加一个元素到头部,或者尾部,实现原理是一个链表。插入数据的时候,如果键不存在,就创建新的链表,如果键已经存在则新增内容,如果值全部移除,对于的键也就消失了,链表无论是头操作还是尾操作,效率都极高,但是对中间操作,效率就很低了(链表的特性)
- set
是 string 类型的无序集合,不能重复的集合
- hash
Rdis Hash 是一个键值对的集合,是一个 string 类型的 field 和 value 的映射表,hash 结构特别适合用于存储对象,kv 模式不变,但是 v 是一个键值对,类似 Map 集合
- zset
是 string 类型的有序集合,不能重复的集合,zset 的每一个成员都有一个 double 类型的分数与之对应,Redis 正是通过分数来为集合中的成员进行从小到大的排序,集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1),所以在进行增删改的效率就非常的高,即便访问中间数据效率也不会低
安装
Ubuntu 18.04 安装 Redis
tar -zxvf redis-5.0.7.tar.gzsudo mv redis-5.0.7 /opt/redis-5.0.7cd /opt/redis-5.0.7/sudo apt install gccsudo make -- 如果报错,安装 gcc,在执行 make distclean,在执行 makesudo make install
外网访问
- 方式一:注释 bind 并且把 protected-mode no
- 方式二:使用 bind 设置需要绑定的内网地址,或者 0.0.0.0
- 方式三:设置密码
protected-mode 它的启用有两个条件,第一个是没有使用 bind,第二个是没有设置密
配置
bind 0.0.0.0daemonize yespidfile /home/eric/redis/redis_6379.pidlogfile "/home/eric/redis/redis.log"dir /home/eric/redis
其中有一个 protected-mode yes,指的是保护模式,保护模式的意思是只允许本机允许 redis,如果启用了保护模式,即使注释掉 bind 127.0.0.1,再用外网访问 redis 的时候还是无法连接的,它的启用条件有两个
- 第一个是没有使用 bind
- 第二个是没有设置访问密码
如果,这两个条件其中之一成立了,那么保护模式会自动失效
启动
redis-server ./redis.conf -- 启动服务redis-cli -h 127.0.0.1 -- 启动客户端
Redis 持久化机制
说白了,就是在指定的时间间隔内,将内存当中的数据集快照写入磁盘,它恢复时是将快照文件直接读到内存
什么意思呢?我们都知道,内存当中的数据,如果我们一断电,那么数据必然会丢失,但是玩过redis 的同学应该都知道,我们一关机之后再启动的时候数据是还在的,所以它必然是在redis启动的时候重新去加载了持久化的文件
Redis提供两种方式进行持久化,
- 一种是 RDB 持久化(默认)
- 另外一种是 AOF(append only file)持久化

RDB(Redis Database)
原理是 Redis 会单独创建(fork)一个与当前进程一模一样的子进程来进行持久化,这个子进程的所有数据(变量。环境变量,程序计数器等)都和原进程一模一样,会先将数据写入到一个临时文件中,待持久化结束了,再用这个临时文件替换上次的 RDB 文件,整个过程中,主进程不进行任何的 IO 操作,这就确保了极高的性能
这个持久化文件在哪里
根据配置文件中的 dir 配置,会自动生产 dump.rdb 文件
dir /home/eric/redis
触发机制(根据配置文件配置项)
什么时候 fork 子进程,或者什么时候触发 rdb 持久化机制?
- shutdown 时,如果没有开启 aof,会触发配置文件中默认的快照配置
- 执行 save 命令时,不会 fork 子进程,save 是利用主进程进行持久化,会导致所有操作全部阻塞
- 执行 bgsave 命令时,会 fork 子进程,redis 会在后台异步进行快照操作,同时可以响应客户端的请求,不会阻塞
- 执行 flushall 命令时,会清空数据库中所有的数据,触发 RDB 机制
优化
如果开启了 AOF 机制,那么就可以屏蔽 save 300 10 和 save 60 10000 了save 900 1 // 每 900 秒,有 1 个数据更改就触发一次save 300 10 // 每 300 秒,有 10 个数据更改就触发一次save 60 10000 // 每 60 秒,有 10000 个数据更改就触发一次
禁用 RDB
save "" 或者直接删除所有 save xxx xxx 即可
主从机制的时候,不能关闭 RDB 机制
AOF(Append Only File)
由于 RDB 机制可能会丢失数据(kill),所以出现了 AOF,原理是将 Reids 的操作日志以追加的方式写入文件,读操作是不记录的
注意:AOF 持久化是不会 fork 子进程的,只有 AOF 重写的时候会 fork 子进程
**
这个持久化文件在哪里
根据配置文件中的 dir 配置,生成 appendonly.aof 文件
dir /home/eric/redis
触发机制(根据配置文件配置项)
appendonly yes # 开启 AOF 持久化,默认关闭appendfilename "appendonly.aof" # AOF 的名称,必须以 aof 结尾appendfsync everysec # 表示每秒同步一次
- appendfsync no:等操作系统进行数据缓存,同步到磁盘(快,但是持久化没保证,因为是操作系统来调用,期间不可控)
- appendfsync always:同步持久化,每次发生数据变更时,立即记录到磁盘(慢,很安全)
- appendfsync everysec:表示每秒同步一次(默认值,很快,但可能会丢失一秒以内的数据)
AOF 重写机制

当 AOF 文件增长到一定大小的时候 Redis 能够调用 bgrewriteaof 对日志文件进行重写(或者手动调用 bgrewriteaof 进行重写),当 AOF 文件大小的增长率大于该配置项时自动开启重写(这里指超过原大小的100%)。
auto-aof-rewrite-percentage 100
当 AOF 文件增长到一定大小的时候 Redis 能够调用 bgrewriteaof 对日志文件进行重写 。当AOF 文件大小大于该配置项时自动开启重写
auto-aof-rewrite-min-size 64mb
建议生产环境配置到 G 的级别,因为默认 64mb 太小了,触发重写机制会 fork 进程,造成阻塞
指定是否在后台 bgrewriteaof 期间调用 fsync,默认为 no
- no:表示要调用 fsync,重写期间会阻塞,不会造成数据丢失
- yes:如果无法容忍系统延迟,而可以容忍少量数据丢失,则设置为 yes
no-appendfsync-on-rewrite no
AOF 读取 RDB 文件内容
如果开启了 AOF,原来的 RDB 文件会失效,因为 AOF 的优先级会高于 RDB,所以可以先关闭 AOF,让 Redis 读取 RDB 文件到内存,然后通过命令行的方式开启 AOF(当前有效,关闭失效),让 AOF 读取内存中的数据
config set appendonly yes
然后再关闭 Redis,再开启 AOF 配置,即可。
AOF 协议格式
# set k1 v1*2 # 接下来有两组命令 select 0(默认命令)$6 # 命令长度 6SELECT # SELECT,长度为 6$1 # 命令长度 10 # 0*3 # 接下来有三组命令$3 # 命令长度 3set # set$2 # 命令长度 2k1 # k1$2 # 命令长度 2v1 # v1
混合持久化机制(Redis 4.0 后)
开启混合持久化
4.0 版本的混合持久化默认关闭的,通过 aof-use-rdb-preamble 配置参数控制,yes 则表示开启,no 表示禁用,5.0 版本之后默认开启。
aof-use-rdb-preamble yes
混合持久化是通过 bgrewriteaof 完成的,不同的是当开启混合持久化时,fork 出的子进程先将共享的内存副本全量的以 RDB 方式写入 AOF 文件,然后在将重写缓冲区的增量命令以 AOF 方式写入到文件,写入完成后通知主进程更新统计信息,并将新的含有 RDB 格式和 AOF 格式的 AOF 文件替换旧的的 AOF 文件。简单的说:新的 AOF 文件前半段是 RDB 格式的全量数据后半段是 AOF 格式的增量数据。
- 优点:混合持久化结合了 RDB 持久化 和 AOF 持久化的优点, 由于绝大部分都是 RDB 格式,加载速度快,同时结合 AOF,增量的数据以AOF 方式保存了,数据更少的丢失。
- 缺点:兼容性差,一旦开启了混合持久化,在4.0之前版本都不识别该 AOF 文件,同时由于前部分是 RDB 格式,阅读性较差
小总结:
Redis提供了 RDB 持久化方案,为什么还要 AOF?
优化数据丢失问题,RDB 会丢失最后一次快照后的数据,AOF 丢失不会超过 2 秒的数据
如果 AOF 和 RDB 同时存在,听谁的?
AOF
RDB 和 AOF 优势劣势
- RDB 适合大规模的数据恢复,对数据完整性和一致性不高,在一定间隔时间做一次备份,如果Redis 意外宕机的话,就会丢失最后一次快照后的所有操作
- AOF 根据配置项而定
官方建议:两种持久化机制同时开启,如果两个同时开启,优先使用 AOF 持久化机制
性能建议(这里只针对单机版redis持久化做性能建议):
因为 RDB 文件只用作后备用途,只要15分钟备份一次就够了,只保留 save 900 1 这条规则。
如果开启 AOF,好处是在最恶劣情况下也只会丢失不超过两秒数据,启动脚本较简单只加载自己的AOF文件就可以了。代价,一是带来了持续的 IO,二是 AOF rewrite 的最后将 rewrite 过程中产生的新数据写到新文件造成的阻塞几乎是不可避免的。
只要硬盘许可,应该尽量减少 AOF rewrite 的频率,AOF 重写的基础大小默认值 64M 太小了,可以设到 5G 以上。默认超过原大小 100% 大小时重写可以改到适当的数值。
