文章目录

  • Redis 入门基础
  • Redis五种数据结构
  • 字符串string
  • 哈希hash
  • 列表list
  • 集合set
  • 有序集合zset
  • 其他命令
  • Redis核心原理
  • redis单线程为什么这么快
  • Redis配置文件详解
  • Redis持久化
  • 1.RDB快照(snapshot)
  • 2.AOF(append-only file)
  • RDB和AOF对比
  • 3.混合持久化(RDB+AOF)
  • 相关文章


Redis 入门基础

Redis五种数据结构

  • 字符串string
  • 哈希hash
  • 列表list
  • 集合set
  • 有序集合zset

对redis来说,所有的key(键)都是字符串

字符串string

是redis中最基本的数据类型,一个key对应一个value。
String类型是二进制安全的,意思是 redis 的 string 可以包含任何数据。如数字,字符串,jpg图片或者序列化的对象。
常用操作命令

SET key value 			//存入字符串键值对
MSET key value [key value ...] 	//批量存储字符串键值对
SETNX key value 		//存入一个不存在的字符串键值对
GET key 			//获取一个字符串键值
MGET key [key ...]	 	//批量获取字符串键值
DEL key [key ...] 		//删除一个键
EXPIRE key seconds 		//设置一个键的过期时间(秒)

# 原子加减
INCR key 			//将key中储存的数字值加1
DECR key 			//将key中储存的数字值减1
INCRBY key increment 		//将key所储存的值加上increment
DECRBY key decrement 	//将key所储存的值减去decrement
哈希hash

是一个Mapmap,指值本身又是一种键值对结构,如 value={{field1,value1},…fieldN,valueN}}
常用操作命令

HSET key field value 					//存储一个哈希表key的键值
HSETNX key field value 					//存储一个不存在的哈希表key的键值
HMSET key field value [field value ...]  //在一个哈希表key中存储多个键值对
HGET key field 							//获取哈希表key对应的field键值
HMGET key field [field ...] 			 //批量获取哈希表key中多个field键值
HDEL key field [field ...] 				 //删除哈希表key中的field键值
HLEN key								//返回哈希表key中field的数量
HGETALL key								//返回哈希表key中所有的键值
HINCRBY key field increment 			 //为哈希表key中field键的值加上增量increment
列表list

List 说白了就是链表(redis 使用双端链表实现的 List),是有序的,value可以重复,可以通过下标取出对应的value值,左右两边都能进行插入和删除数据。
常用操作命令

LPUSH key value [value ...] 		//将一个或多个值value插入到key列表的表头(最左边)
RPUSH key value [value ...]	 		//将一个或多个值value插入到key列表的表尾(最右边)
LPOP key						 //移除并返回key列表的头元素
RPOP key						 //移除并返回key列表的尾元素
LRANGE key start stop			  //返回列表key中指定区间内的元素,区间以偏移量start和stop指定
BLPOP key [key ...] timeout		  //从key列表表头弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0,一直阻塞等待
BRPOP key [key ...] timeout 	  //从key列表表尾弹出一个元素,若列表中没有元素,阻塞等待timeout秒,如果timeout=0,一直阻塞等待
集合set

集合类型也是用来保存多个字符串的元素,但和列表不同的是集合中 1. 不允许有重复的元素,2.集合中的元素是无序的,不能通过索引下标获取元素,3.支持集合间的操作,可以取多个集合取交集、并集、差集。
常用操作命令

#Set常用操作
SADD key member [member ...]			//往集合key中存入元素,元素存在则忽略,若key不存在则新建
SREM key member [member ...]			//从集合key中删除元素
SMEMBERS key					//获取集合key中所有元素
SCARD key					//获取集合key的元素个数
SISMEMBER key member			//判断member元素是否存在于集合key中
SRANDMEMBER key [count]			//从集合key中选出count个元素,元素不从key中删除
SPOP key [count]				//从集合key中选出count个元素,元素从key中删除

#Set运算操作
SINTER key [key ...] 				//交集运算
SINTERSTORE destination key [key ..]		//将交集结果存入新集合destination中
SUNION key [key ..] 				//并集运算
SUNIONSTORE destination key [key ...]		//将并集结果存入新集合destination中
SDIFF key [key ...] 				//差集运算
SDIFFSTORE destination key [key ...]		//将差集结果存入新集合destination中

#集合操作
SINTER set1 set2 set3 { c }
SUNION set1 set2 set3 { a,b,c,d,e }
SDIFF set1 set2 set3 { a }
有序集合zset

有序集合和集合有着必然的联系,保留了集合不能有重复成员的特性,区别是,有序集合中的元素是可以排序的,它给每个元素设置一个分数,作为排序的依据。(有序集合中的元素不可以重复,但是score 分数 可以重复,就和一个班里的同学学号不能重复,但考试成绩可以相同)。
常用操作命令

#Zset常用操作
ZADD key score member [[score member]…]	//往有序集合key中加入带分值元素
ZREM key member [member …]		//从有序集合key中删除元素
ZSCORE key member 			//返回有序集合key中元素member的分值
ZINCRBY key increment member		//为有序集合key中元素member的分值加上increment 
ZCARD key				//返回有序集合key中元素个数
ZRANGE key start stop [WITHSCORES]	//正序获取有序集合key从start下标到stop下标的元素
ZREVRANGE key start stop [WITHSCORES]	//倒序获取有序集合key从start下标到stop下标的元素

Zset集合操作
ZUNIONSTORE destkey numkeys key [key ...] 	//并集计算
ZINTERSTORE destkey numkeys key [key …]	//交集计算
其他命令

keys:全量遍历键,用来列出所有满足特定正则字符串规则的key,当redis数据量比较大时,性能比较差,要避免使用
scan:渐进式遍历键

SCAN cursor [MATCH pattern] [COUNT count] [TYPE type]
scan 参数提供了四个参数,第一个是 cursor 整数值;第二个是 key 的正则模式;第三个是一次遍历的key的数量,并不是符合条件的结果数量;第四个是需要查询的数据类型。第一次遍历时,cursor 值为 0,然后将返回结果中第一个整数值作为下一次遍历的 cursor。一直遍历到返回的 cursor 值为 0 时结束。

Info: 查看redis服务运行信息,分为 9 大块,每个块都有非常多的参数,这 9 个块分别是:

Server 服务器运行的环境参数 
Clients 客户端相关信息 
Memory 服务器运行内存统计数据 
Persistence 持久化信息 
Stats 通用统计数据 
Replication 主从复制相关信息 
CPU CPU 使用情况 
Cluster 集群信息 
KeySpace 键值对统计数量信息

Redis核心原理

记住:redis是单线程的

redis单线程为什么这么快

原因

  • 1,单线程避免了多线程之间切换竞争的性能损耗问题
  • 2,所有的数据都在内存中,所有的运算都是内存级别的运算;使用内存减少了磁盘IO
  • 3,对于高并发的情况,redis采用IO多路复用来处理并发客户端连接

注意
由于redis是单线程的,所以要小心使用 Redis 指令,对于那些耗时的指令(比如keys),一定要谨慎使用,一不小心就可能会导致 Redis 卡顿。

redis的IO多路复用(先简单了解,后续在深入)

Redis的IO多路复用:redis利用epoll来实现IO多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器,事件分派器将事件分发给事件处理器。

redis 32 绿色下载 redis6.2.0_Redis

查看redis最大链接数命令

# 查看redis支持的最大连接数,在redis.conf文件中可修改,# maxclients 10000
127.0.0.1:6379> CONFIG GET maxclients
1) "maxclients"
2) "10000"

Redis配置文件详解

redis.conf

# Redis配置文件示例。
#
# 在启动redis-server时指定应该加载的配置文件
#
# ./redis-server /path/to/redis.conf

# Note on units: when memory size is needed, it is possible to specify
# it in the usual form of 1k 5GB 4M and so forth:
#
# 
# 1k => 1000 bytes
# 1kb => 1024 bytes
# 1m => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes
#
# units are case insensitive so 1GB 1Gb 1gB are all the same.
# 上面的意思就是关于内存大小的设置,单位是不区分大小写

################################## INCLUDES ###################################

# 引入其它配置文件。比如说当你有多个server,而有一些配置项是它们公用的, 
# 那么你可以将这些公用的配置项写进一个配置文件common.conf里,
# 然后这些server再include这个配置文件,这些server自己的配置项则分别写在自己的配置文件里。
#
# include /path/to/local.conf
# include /path/to/other.conf

################################## MODULES #####################################

# 启动时加载模块,如果server无法加载模块,则此配置会被忽略。可以使用多个loadmodule。
# 具体不清楚
#
# loadmodule /path/to/my_module.so
# loadmodule /path/to/other_module.so

################################## NETWORK #####################################

# 指定 redis 只接收来自于该IP地址的请求,如果不进行设置,那么将处理所有请求
# 你可以绑定单一接口,如果没有绑定,所有接口都会监听到来的连接
#
# 例子:
#
# bind 192.168.1.100 10.0.0.1
# bind 127.0.0.1 ::1
#
bind 127.0.0.1

# 设置外部网络连接redis服务;默认是yes,即开启;设置方式如下:
# 1、关闭protected-mode模式,此时外部网络可以直接访问
# 2、开启protected-mode保护模式,需配置bind ip或者设置访问密码
#
protected-mode yes

# redis监听的端口号
#
port 6379

# tcp连接积压最大值
# 这个值的大小是受somaxconn影响的, 因为是取的它们两者的最小值, 所以如果要调大的话必需修改内核的somaxconn值.
# 此参数确定了TCP连接中已完成队列(完成三次握手之后)的长度, # 当然此值必须不大于Linux系统定义的/proc/sys/net/core/somaxconn值,默认是511,
# 而Linux的默认参数值是128。当系统并发量大并且客户端速度缓慢的时候,可以将这二个参数一起参考设定。
#
tcp-backlog 511

# unix Socket的链接相关参数,听说速度比tcp链接快很多
# unixsocket配置项来指定unix socket文件的路径,并通过unixsocketperm来指定文件的权限
#
# unixsocket /tmp/redis.sock
# unixsocketperm 700

# 此参数为设置客户端空闲超过timeout,服务端会断开连接,为0则服务端不会主动断开连接,不能小于0
timeout 0

# TCP keepalive.
#
# TCP连接保活策略,可以通过tcp-keepalive配置项来进行设置,单位为秒,假如设置为60秒,
# 则server端会每60秒向连接空闲的客户端发起一次ACK请求,以检查客户端是否已经挂掉,对于无响应的客户端则会关闭其连接。
# 所以关闭一个连接最长需要120秒的时间。如果设置为0,则不会进行保活检测。
#
tcp-keepalive 300

################################# TLS/SSL #####################################

# By default, TLS/SSL is disabled. To enable it, the "tls-port" configuration
# directive can be used to define TLS-listening ports. To enable TLS on the
# default port, use:
#
# port 0
# tls-port 6379

# Configure a X.509 certificate and private key to use for authenticating the
# server to connected clients, masters or cluster peers.  These files should be
# PEM formatted.
#
# tls-cert-file redis.crt 
# tls-key-file redis.key

# Configure a DH parameters file to enable Diffie-Hellman (DH) key exchange:
#
# tls-dh-params-file redis.dh

# Configure a CA certificate(s) bundle or directory to authenticate TLS/SSL
# clients and peers.  Redis requires an explicit configuration of at least one
# of these, and will not implicitly use the system wide configuration.
#
# tls-ca-cert-file ca.crt
# tls-ca-cert-dir /etc/ssl/certs

# By default, clients (including replica servers) on a TLS port are required
# to authenticate using valid client side certificates.
#
# It is possible to disable authentication using this directive.
#
# tls-auth-clients no

# By default, a Redis replica does not attempt to establish a TLS connection
# with its master.
#
# Use the following directive to enable TLS on replication links.
#
# tls-replication yes

# By default, the Redis Cluster bus uses a plain TCP connection. To enable
# TLS for the bus protocol, use the following directive:
#
# tls-cluster yes

# Explicitly specify TLS versions to support. Allowed values are case insensitive
# and include "TLSv1", "TLSv1.1", "TLSv1.2", "TLSv1.3" (OpenSSL >= 1.1.1) or
# any combination. To enable only TLSv1.2 and TLSv1.3, use:
#
# tls-protocols "TLSv1.2 TLSv1.3"

# Configure allowed ciphers.  See the ciphers(1ssl) manpage for more information
# about the syntax of this string.
#
# Note: this configuration applies only to <= TLSv1.2.
#
# tls-ciphers DEFAULT:!MEDIUM

# Configure allowed TLSv1.3 ciphersuites.  See the ciphers(1ssl) manpage for more
# information about the syntax of this string, and specifically for TLSv1.3
# ciphersuites.
#
# tls-ciphersuites TLS_CHACHA20_POLY1305_SHA256

# When choosing a cipher, use the server's preference instead of the client
# preference. By default, the server follows the client's preference.
#
# tls-prefer-server-ciphers yes

# By default, TLS session caching is enabled to allow faster and less expensive
# reconnections by clients that support it. Use the following directive to disable
# caching.
#
# tls-session-caching no

# Change the default number of TLS sessions cached. A zero value sets the cache
# to unlimited size. The default size is 20480.
#
# tls-session-cache-size 5000

# Change the default timeout of cached TLS sessions. The default timeout is 300
# seconds.
#
# tls-session-cache-timeout 60

################################# GENERAL #####################################

# 守护进程
# 是否在后台执行,yes:后台运行;no:不是后台运行
# 
daemonize no

# If you run Redis from upstart or systemd, Redis can interact with your
# 可以通过upstart和systemd管理Redis守护进程,这个参数是和具体的操作系统相关的。
#
supervised no

# 配置pid文件路径。当redis以守护模式启动时,如果没有配置pidfile,pidfile默认值是/var/run/redis.pid
# 
pidfile /local/redis-6.0.6/redis_6379.pid

# 日志级别。可选项有:debug(记录大量日志信息,适用于开发、测试阶段);  
#                     verbose(较多日志信息);  
#                     notice(适量日志信息,使用于生产环境);
#                     warning(仅有部分重要、关键信息才会被记录)
#
loglevel notice

# 日志文件的位置,当指定为空字符串时,为标准输出,如果redis已守护进程模式运行,那么日志将会输出到  /dev/null 
#
logfile ""

# 是否把日志记录到系统日志。
#
# syslog-enabled no

# 设置系统日志的标识符
#
# syslog-ident redis

# 指定syslog设备(facility),必须是user或则local0到local7。
#
# syslog-facility local0

# 设置数据库的数目。默认的数据库是DB 0 ,
# 可以在每个连接上使用select  <dbid> 命令选择一个不同的数据库,dbid是一个介于0到databases - 1 之间的数值。
#
databases 16

# 是否总是显示logo
#
always-show-logo yes

################################ SNAPSHOTTING  ################################
#
# 保存数据到磁盘。格式是:save <seconds> <changes> ,含义是在 seconds 秒之后至少有 changes个keys 发生改变则保存一次。
# 官方出厂配置默认是 900秒内有1个更改,300秒内有10个更改以及60秒内有10000个更改,则将内存中的数据快照写入磁盘。
# 若不想用RDB方案,可以把 save "" 的注释打开,下面三个注释
#
#   save ""
#
save 900 1
save 300 10
save 60 10000

# 持久化出现错误后,是否依然进行继续进行工作
# 当RDB持久化出现错误后,是否依然进行继续进行工作,yes:不能进行工作,no:可以继续进行工作
#
stop-writes-on-bgsave-error yes

# 配置存储至本地数据库时是否压缩数据,默认为yes。Redis采用LZF压缩方式,但占用了一点CPU的时间。
# 若关闭该选项,但会导致数据库文件变的巨大。建议开启。
#
rdbcompression yes

# 是否校验rdb文件;从rdb格式的第五个版本开始,在rdb文件的末尾会带上CRC64的校验。
# 这有利于文件的容错性,但是在保存rdb文件的时候,会有大概10%的性能损耗,所以如果你追求高性能,可以关闭该配置
#
rdbchecksum yes

# 指定本地数据库文件名,一般采用默认的dump.rdb
#
dbfilename dump.rdb

# rdb文件是否删除同步锁
#
rdb-del-sync-files no

# 数据库存放目录。必须是一个目录,aof文件也会保存到该目录下。
#
dir ./

################################# REPLICATION #################################

# 设置主节点ip,主节点端口
#
# replicaof <masterip> <masterport>

# 主节点密码
# 如果master设置了requirepass,那么slave要连上master,需要有master的密码才行。
# masterauth就是用来配置master的密码,这样可以在连上master后进行认证。
#
# masterauth <master-password>
#
# 主节点用户名
# 当指定了masteruser时,副本将使用新的身份验证表单对其主进行身份验证
# 当指定了masteruser时,副本将使用新的身份验证表单对其主进行身份验证
#
# masteruser <username>

# 当一个slave失去和master的连接,或者同步正在进行中,slave的行为有两种可能:
# 1) 如果 replica-serve-stale-data 设置为 "yes" (默认值),slave会继续响应客户端请求,可能是正常数据,也可能是还没获得值的空数据。
# 2) 如果 replica-serve-stale-data 设置为 "no",slave会回复"正在从master同步(SYNC with master in progress)"来处理各种请求,除了 INFO 和 SLAVEOF 命令。
#
replica-serve-stale-data yes

# 你可以配置salve实例是否接受写操作。
# 可写的slave实例可能对存储临时数据比较有用(因为写入salve# 的数据在同master同步之后将很容被删除),
# 但是如果客户端由于配置错误在写入时也可能产生一些问题。
# 从Redis2.6默认所有的slave为只读
# 注意:只读的slave不是为了暴露给互联网上不可信的客户端而设计的。它只是一个防止实例误用的保护层。
# 一个只读的slave支持所有的管理命令比如config,debug等。为了限制你可以用'rename-command'来隐藏所有的管理和危险命令来增强只读slave的安全性。
#
replica-read-only yes

# 同步策略: 磁盘或socket,默认磁盘方式
#
repl-diskless-sync no

# 如果非磁盘同步方式开启,可以配置同步延迟时间,以等待master产生子进程通过socket传输RDB数据给slave。
# 默认值为5秒,设置为0秒则每次传输无延迟。
#
repl-diskless-sync-delay 5

#
# "disabled"    - 不要使用无磁盘加载(首先将rdb文件存储到磁盘)
# "on-empty-db" - 只有在完全安全的情况下才使用无磁盘加载。
# "swapdb"      - 在直接从套接字解析数据时,在RAM中保留当前db内容的副本。注意,这需要足够的内存,如果没有内存,就会面临OOM被杀死的风险。
#
repl-diskless-load disabled

# 定义心跳(PING)间隔。
# 单位秒
#
# repl-ping-replica-period 10

# 这个参数一定不能小于repl-ping-replica-period,可以考虑为repl-ping-replica-period的3倍或更大。
# 定义多长时间内均PING不通时,判定心跳超时。
# 对于redis集群,达到这个值并不会发生主从切换,主从何时切换由参数cluster-node-timeout控制,只有master状态为fail后,它的slaves才能发起选举。
#
# repl-timeout 60

# 是否禁止复制tcp链接的tcp nodelay参数,可传递yes或者no。默认是no
# 即使用tcp nodelay。
# 如果master设置了yes来禁止tcp nodelay设置,在把数据复制给slave的时候,会减少包的数量和更小的网络带宽。
# 但是这也可能带来数据的延迟。默认我们推荐更小的延迟,但是在数据量传输很大的场景下,建议选择yes。
#
repl-disable-tcp-nodelay no

# 复制缓冲区大小
# 保存复制的命令。
# 当从节点在一段时间内断开连接时,主节点会收集数据到backlog这个缓冲区,
# 因此当一个从节点想要重新连接时,通常不需要完全的重新同步,但是部分的重新同步就足够了,
# 只是通过在断开连接的时候传递数据的一部分。默认是1mb
#
# repl-backlog-size 1mb

# 当主节点不再联系从节点,则释放backlog(内存)
# master没有slave一段时间会释放复制缓冲区的内存,repl-backlog-ttl用来设置该时间长度。单位为秒。
#
# repl-backlog-ttl 3600

# 这是 replicas 节点通过 INFO 接口给出的信息,默认值为 100
# 当 master 节点无法正常工作后 Redis Sentinel 通过这个值来决定将哪个 replicas 节点提升为 master 节点。
# 这个数值越小表示越优先进行提升。
# 如有三个 replicas 节点其 priority 值分别为 10,100,25, Sentinel 会选择 priority 为 10 的节点进行提升。
# 这个值为 0 表示 replica 节点永远不能被提升为 master 节点。
#
replica-priority 100

# redis提供了可以让master停止写入的方式,
# 如果配置了min-replicas-to-write,健康的slave的个数小于N,mater就禁止写入。
# master最少得有多少个健康的slave存活才能执行写命令。
# 这个配置虽然不能保证N个slave都一定能接收到master的写操作,但是能避免没有足够健康的slave的时候,master不能写入来避免数据丢失。
# 设置为0是关闭该功能
#
# min-replicas-to-write 3

# 延迟小于min-replicas-max-lag秒的slave才认为是健康的slave
#
# min-replicas-max-lag 10

# 常用于端口转发或NAT场景下,对Master暴露真实IP和端口信息。
#
# replica-announce-ip 5.5.5.5
# replica-announce-port 1234

############################### KEYS TRACKING #################################

# 当有一个新的键被 tracking 时,若是当前 tracking 的 key 的数目大于 tracking_table_max_keys,
# 则会随机删除之前 tracking 的 key,而且向对应的客户端发送失效新闻。
#
# tracking-table-max-keys 1000000

################################## SECURITY ###################################

# ACL日志的最大长度,默认是128M
# 关于acl,详见:https://redis.io/topics/acl
#
acllog-max-len 128

# 设置密码
#
# requirepass foobared

# 把危险的命令给修改成其他名称。
# 比如CONFIG命令可以重命名为一个很难被猜到的命令,这样用户不能使用,而内部工具还能接着使用
# 设置成一个空的值,可以禁止一个命令
#
# 例子:
#
# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52
#
# rename-command CONFIG ""


################################### CLIENTS ####################################

# 设置能连上redis的最大客户端连接数量
# 默认是10000个客户端连接。
#由于redis不区分连接是客户端连接还是内部打开文件或者和slave连接等,所以maxclients最小建议设置到32。
# 如果超过了maxclients,redis会给新的连接发送’max number of clients reached’,并关闭连接
#
# maxclients 10000

############################## MEMORY MANAGEMENT ################################

# redis配置的最大内存容量
# 当内存满了,需要配合maxmemory-policy策略进行处理。
# 注意slave的输出缓冲区是不计算在maxmemory内的。所以为了防止主机内存使用完,建议设置的maxmemory需要更小一些
#
# maxmemory <bytes>

# 内存达到上限的处理策略:
# volatile-lru -> 仅使用带过期集的密钥,使用近似的LRU进行驱逐。
# allkeys-lru -> 使用近似的LRU驱逐任何密钥。
# volatile-lfu -> 仅使用带过期集的密钥,使用近似的LFU驱逐。
# allkeys-lfu -> 使用近似的LFU驱逐任何密钥。
# volatile-random -> 删除具有过期集的随机键。
# allkeys-random -> 删除一个随机的键,任何键。
# volatile-ttl -> 删除最近过期时间的密钥(较小的TTL)
# noeviction -> 不移除任何key,只是返回一个写错误。
#
# maxmemory-policy noeviction

# lru检测的样本数。使用lru或者ttl淘汰算法,从需要淘汰的列表中随机选择sample个key,选出闲置时间最长的key移除
#
# maxmemory-samples 5

# 默认值为yes,是否忽略从节点的内存限制。
#
# replica-ignore-maxmemory yes

# Redis以两种方式回收过期的密钥:在访问时发现过期的密钥,
# 以及在后台,在所谓的“活动过期密钥”。密钥空间被缓慢而交互式地扫描,
# 以寻找要回收的过期密钥,这样就可以释放过期且在短时间内再也不会被访问的密钥的内存
#
# 过期周期的默认努力将试图避免在内存中仍然有超过10%的过期密钥,
# 并试图避免消耗总内存的25%以上,并增加系统的延迟。
# 但是,可以将通常设置为“1”的过期“努力”增加到更大的值,直到值“10”。
# 在它的最大值,系统将使用更多的CPU,更长的周期(技术上可能引入更多的延迟),
# 并将减少系统中仍然存在的已经过期的密钥。这是内存、CPU和内存之间的权衡。
#
# active-expire-effort 1

############################# LAZY FREEING ####################################

# 延迟加载
# 内存满逐出选项
lazyfree-lazy-eviction no
# 过期key删除选项
lazyfree-lazy-expire no
# 内部删除选项
lazyfree-lazy-server-del no
# replica client做全同步的时候,是否异步flush本地db,如果内存变动不大,建议可开启。
# 可减少全量同步耗时,从而减少主库因输出缓冲区爆涨引起的内存使用增长。
replica-lazy-flush no

# 针对有些指令在处理已存在的键时,会带有一个隐式的DEL键的操作
#
lazyfree-lazy-user-del no

################################ THREADED I/O #################################

# 启用的io线程数量
# 如果你的server有4个核心,尝试把这个值设置为3
# 如果有8个核心,尝试把这个值设置为6
# 但这个值不建议超过8
#
# io-threads 4
#
# 读请求也使用io线程
# 当I/O threads被启用时,线程仅用于写,
# 如果需要把读数据和协议解析也启用线程,
# 则需要把io-threads-do-reads也设置为yes
#
# io-threads-do-reads no

############################## APPEND ONLY MODE ###############################

# 是否以append only模式作为持久化方式
# 默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了。
# 但是redis如果中途宕机,会导致可能有几分钟的数据丢失,根据save来策略进行持久化,
# Append Only File是另一种持久化方式,可以提供更好的持久化特性。
# Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,
#每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。
#
appendonly no

# AOF 文件名称
#
appendfilename "appendonly.aof"

# aof持久化策略的配置
# no-->表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快。
# always-->表示每次写入都执行fsync,以保证数据同步到磁盘。
# everysec-->表示每秒执行一次fsync,可能会导致丢失这1s数据。
#
appendfsync everysec


# 在aof重写或者写入rdb文件的时候,会执行大量IO,此时对于everysec和always的aof模式来说,
# 执行fsync会造成阻塞过长时间,no-appendfsync-on-rewrite字段设置为默认设置为no,
# 如果对延迟要求很高的应用,这个字段可以设置为yes,否则还是设置为no,
# 这样对持久化特性来说这是更安全的选择。
# 设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,
# 默认为no,建议yes。Linux的默认fsync策略是30秒。可能丢失30秒数据。
#
no-appendfsync-on-rewrite no

# AOF自动重写配置
# 当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写,
# 即当aof文件增长到一定大小的时候Redis能够调用bgrewriteaof对日志文件进行重写。
# 当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,自动启动新的日志重写过程
#
auto-aof-rewrite-percentage 100
# 设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写
auto-aof-rewrite-min-size 64mb

# 是否redis在启动时可以加载被截断的AOF文件
#
aof-load-truncated yes

# 混合 RDB-AOF 持久化格式
# 这是一个可选的功能,
# 在开启了这个功能之后, AOF 重写产生的文件将同时包含 RDB 格式的内容和 AOF 格式的内容, 
# 其中 RDB 格式的内容用于记录已有的数据, 而 AOF 格式的内存则用于记录最近发生了变化的数据, 
# 这样 Redis 就可以同时兼有 RDB 持久化和 AOF 持久化的优点 —— 既能够快速地生成重写文件, 也能够在出现问题时, 快速地载入数据。
# 这个功能可以通过aof-use-rdb-preamble 选项进行开启
#
aof-use-rdb-preamble yes

################################ LUA SCRIPTING  ###############################

# 限制lua脚本的最长运行时间,默认为5秒钟。
# 当脚本运行时间超过这一限制后,Redis将开始接受其他命令但不会执行
# (以确保脚本的原子性,因为此时脚本并没有被终止),而是会返回“BUSY”错误。
#
lua-time-limit 5000

################################ REDIS CLUSTER  ###############################

# 集群开关,默认是不开启集群模式。
#
# cluster-enabled yes

# 集群配置文件的名称
# 这个文件应该和redis配置文件区别开
# 每个节点都有一个集群相关的配置文件,持久化保存集群的信息
#
# cluster-config-file nodes-6379.conf

# 节点相互连接的超时时间
#
# cluster-node-timeout 15000

# 在进行故障转移的时候,全部slave都会请求申请为master,
# 但是有些slave可能与master断开连接一段时间了,导致数据过于陈旧,这样的slave不应该被提升为master。
# 该参数就是用来判>断slave节点与master断线的时间是否过长。判断方法是:
# 比较slave断开连接的时间和(node-timeout *slave-validity-factor) + repl-ping-slave-period
# 如果节点超时时间为三十秒, 并且slave-validity-factor为10,假设默认的repl-ping-slave-period是10秒,即如果超过310秒slave将不会尝试进行故障转移
# 可能出现由于某主节点失联却没有从节点能顶上的情况,从而导致集群不能正常工作,在这种情况下,只有等到原来的主节点重新回归到集群,集群才恢复运作
# 如果设置成0,则无论从节点与主节点失联多久,从节点都会尝试升级成主节
# redis 5.0之后是 cluster-replica-validity-factor
#
# cluster-replica-validity-factor 10

# 主节点需要的最小从节点数,只有达到这个数,主节点失败时,它从节点才会进行迁移
#
# cluster-migration-barrier 1

# 当一定比例的键空间没有被覆盖到(就是某一部分的哈希槽没了,有可能是暂时挂了),
# 集群就停止处理任何查询操作。如果该项设置为no,那么就算请求中只有一部分的键可以被查到,一样可以查询(但是有可能会查不全)
#
# cluster-require-full-coverage yes

# 选项设置为yes时,会阻止replicas尝试对其master在主故障期间进行故障转移 
#然而,master仍然可以执行手动故障转移,如果强制这样做的话
#
# cluster-replica-no-failover no

# 如果将其设置为no(默认情况下为默认值),则当Redis群集被标记为失败或节点无法到达时,
# 该节点将停止为所有流量提供服务达不到法定人数或完全覆盖。这样可以防止从不知道群集更改的节点读取可能不一致的数据。
# 可以将此选项设置为yes,以允许在失败状态期间从节点进行读取,这对于希望优先考虑读取可用性但仍希望防止写入不一致的应用程序很有用。
# 当仅使用一个或两个分片的Redis Cluster时,也可以使用它,因为它允许节点在主服务器发生故障但无法进行自动故障转移时继续为写入提供服务。
#
# cluster-allow-reads-when-down no

########################## CLUSTER DOCKER/NAT support  ########################

# 实际为各节点网卡分配ip 先用上网关ip代替
# cluster-announce-ip 10.1.1.5
# 节点映射端口
# cluster-announce-port 6379
# 节点总线端
# cluster-announce-bus-port 6380

################################## SLOW LOG ###################################

# 执行时间比slowlog-log-slower-than大的请求记录到slowlog里面,单位是微秒,所以1000000就是1秒。
# 注意,负数时间会禁用慢查询日志,而0则会强制记录所有命令。
#
slowlog-log-slower-than 10000

# 慢查询日志长度
# 当一个新的命令被写进日志的时候,最老的那个记录会被删掉。这个长度没有限制。只要有足够的内存就行。你可以通过 SLOWLOG RESET 来释放内存
slowlog-max-len 128

################################ LATENCY MONITOR ##############################

# 延迟监控功能是用来监控redis中执行比较缓慢的一些操作,用LATENCY打印redis实例在跑命令时的耗时图表。
# 只记录大于等于下边设置的值的操作。0的话,就是关闭监视。
# 默认延迟监控功能是关闭的,如果你需要打开,也可以通过CONFIG SET命令动态设置。
latency-monitor-threshold 0

############################# EVENT NOTIFICATION ##############################

# 在 Redis 里面有一些事件,比如键到期、键被删除等。然后我们可以通过配置一些东西来让 Redis 一旦触发这些事件的时候就往特定的 Channel 推一条消息。
# 大致的流程就是我们给 Redis 的某一个 db 设置过期事件,使其键一旦过期就会往特定频道推消息,我在自己的客户端这边就一直消费这个频道就好了。
# 以后一来一条定时任务,我们就把这个任务状态压缩成一个键,并且过期时间为距这个任务执行的时间差。
# 那么当键一旦到期,就到了任务该执行的时间,Redis自然会把过期消息推去,我们的客户端就能接收到了。这样一来就起到了定时任务的作用。

# 空间通知特性的开启
# 双引号内参数为空,表示默认为不开启的设置。参数不为空则表示开启此特性。
# 参数的配置,是以字符组合为准。每个字符(注意大小写)对应允许的操作,如下:
# K     Keyspace events, published with __keyspace@<db>__ prefix.
# E     Keyevent events, published with __keyevent@<db>__ prefix.
# g     Generic commands (non-type specific) like DEL, EXPIRE, RENAME, ...
# $     String commands
# l     List commands
# s     Set commands
# h     Hash commands
# z     Sorted set commands
# x     Expired events (events generated every time a key expires)
# e     Evicted events (events generated when a key is evicted for maxmemory)
# A     Alias for g$lshzxe, so that the "AKE" string means all the events.
#
notify-keyspace-events ""

############################### GOPHER SERVER #################################

# 如果您计划将Redis放在互联网上一个公众可访问的地址
# 到服务器Gopher页面,请确保为实例设置了密码。
# 一旦设置了密码:
#
# 1。Gopher服务器(启用时,而不是默认情况下)仍将提供服务
# 通过Gopher发布内容。
# 2。但是在客户端调用之前不能调用其他命令
# 进行身份验证。
# 所以使用'requirepass'选项来保护您的实例。
# 要启用Gopher支持,请取消对下列行的注释并设置选项从no(默认值)变为yes。
#
# gopher-enabled no

############################### ADVANCED CONFIG ###############################

# 数据量小于等于hash-max-ziplist-entries的用ziplist,大于hash-max-ziplist-entries用hash
#
hash-max-ziplist-entries 512
# value大小小于等于hash-max-ziplist-value的用ziplist,大于hash-max-ziplist-value用hash
#
hash-max-ziplist-value 64

# 数据量小于等于list-max-ziplist-entries用ziplist,大于list-max-ziplist-entries用list
# 负数用来表示list所占的字节数,小于该字节数时使用ZIPLIST存储,超过则使用LINKLIST存储
# -1:4KB,-2:8KB,-3:16KB,-4:32KB,-5:64KB
# 该值如果为正数表示元素的个数,小于该配置的数量使用ZIPLIST存储,超过则使用LINKLIST存储
#
list-max-ziplist-size -2

# 列表很长时,访问两端数据的频率高于中间的数据。该选项可以将list中间的数据节点进行压缩,节省内存空间
# 0:表示不压缩,默认值
# 1:表示list两端各有一个节点不压缩
# 2:表示list两端各有两个节点不压缩
# n:表示list两端各有n个几点不压缩
list-compress-depth 0

# 数据量小于等于set-max-intset-entries用iniset,大于set-max-intset-entries用set
#
set-max-intset-entries 512

# 数据量小于等于zset-max-ziplist-entries用ziplist,大于zset-max-ziplist-entries用zset
#
zset-max-ziplist-entries 128
# value大小小于等于zset-max-ziplist-value用ziplist,大于zset-max-ziplist-value用zset
# 
zset-max-ziplist-value 64

# value大小小于等于hll-sparse-max-bytes使用稀疏数据结构(sparse),大于hll-sparse-max-bytes使用稠密的数据结构(dense)
#
hll-sparse-max-bytes 3000

# 流宏节点的最大大小/项。流数据结构是一个基数
# 大节点树,其中编码多个项目。使用这个配置
# 可以配置单个节点的字节大小,以及当切换到新节点之前,它可能包含的最大项数添加新的流条目。如果下列任何设置设置为
# 0,限制将被忽略,因此可以只设置
# max通过将最大字节设置为0,将最大条目设置为所需的值来进行限制价值。
stream-node-max-bytes 4096
stream-node-max-entries 100

# rehash的方式是否启用activerhashing
# hash table是一种高效的数据结构,被广泛的用在key-value存储中,Redis的dict其实就是一个典型的hash table实现。
# rehash是在hash table的大小不能满足需求,造成过多hash碰撞后需要进行的扩容hash table的操作,
# 其实通常的做法确实是建立一个额外的hash table,将原来的hash table中的数据在新的数据中进行重新输入,
# 从而生成新的hash表。redis的 rehash包括了lazy rehashing和active rehashing两种方式
# lazy rehashing:在每次对dict进行操作的时候执行一个slot的rehash
# active rehashing:每100ms里面使用1ms时间进行rehash。

# 当你的使用场景中,有非常严格的实时性需要,不能够接受Redis时不时的对请求有2毫秒的延迟的话,把这项配置为no。
# 如果没有这么严格的实时性要求,可以设置为yes,以便能够尽可能快的释放内存。
#
activerehashing yes

# 客户端类型:
# normarl: 普通客户端
# slave: 从节点作为客户端
# pub/sub: 发布与订阅的客户端
# 
# 缓冲区大小限制类型:
# hard limit: 缓冲区大小的硬性限制,即阀值最大值,一旦达到就立刻关闭连接
# soft limit: 缓冲去大小的软性限制,即容忍值,它和seconds配合,如果buffer值超过soft且持续时间达到了seconds,也立刻关闭
#
# client-output-buffer-limit参数限制分配的缓冲区的大小,防止内存无节制的分配。参数的默认值都为0,意思是不做任何限制。
#
# 一般的话最好都要设置这个参数:
# 
# client buffer实际上是占用redis的数据内存空间,redis的最大数据内存空间由maxmemory参数限定。
# 当数据内存空间达到maxmemory参数限定值时,redis会开始evict数据,或者直接提示客户端OOM(out of memory),
# 这种情况下主要发生在客户端执行大批量数据读取, 比如keys*、smembers、lrange、hgetall等操作。
# 如果单次查询的数据太多,导致redis的used memory增长一倍。
# 
# 
# 但是client-output-buffer-limit也不能设置太小,这个会导致客户端读取不到数据。
#
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60

# Redis服务端客户端查询缓冲区(用来保存客户端命令)的大小,超过设置值,立即关闭该客户端
#
# client-query-buffer-limit 1gb

# 在Redis协议中,批量请求,即代表单个的元素
# 通常限制为512 mb。但是你可以改变这个限制
#
# proto-max-bulk-len 512mb

# Redis Server执行后台任务的频率,默认值为10,范围1-500
# 通常不建议超过100,值越大表示Redis执行后台任务的次数越频繁,建议采用默认值10
# 后台任务主要包括关闭空闲超时连接、过期集合检测等
#
hz 10

# Redis 5.0版本以后加入,默认开启
# 可以自适应调整hz参数,使得后台任务执行更加频繁,但是会占用更多的CPU。
#
dynamic-hz yes

# AOF文件rewrite过程是否以增量的模式进行文件同步,默认yes,不要设置为no
# rewrite过程中,每产生32M数据进行一次文件同步,可以避免AOF文件提交到磁盘时出现较大的延迟
#
aof-rewrite-incremental-fsync yes

# 同理AOF文件,只不过这个是快照文件
#
rdb-save-incremental-fsync yes

# LFU算法在某些时候,对于使用频繁的key将不再考虑,即便是旧的。防止频繁的key来占用算法。
#
# +--------+------------+------------+------------+------------+------------+
# | factor | 100 hits   | 1000 hits  | 100K hits  | 1M hits    | 10M hits   |
# +--------+------------+------------+------------+------------+------------+
# | 0      | 104        | 255        | 255        | 255        | 255        |
# +--------+------------+------------+------------+------------+------------+
# | 1      | 18         | 49         | 255        | 255        | 255        |
# +--------+------------+------------+------------+------------+------------+
# | 10     | 10         | 18         | 142        | 255        | 255        |
# +--------+------------+------------+------------+------------+------------+
# | 100    | 8          | 11         | 49         | 143        | 255        |
# +--------+------------+------------+------------+------------+------------+
#
# factor越高,可以达到饱和(极限)容纳的key就越多。
# decay-time是计数器的衰变时间。
#
# lfu-log-factor 10
# lfu-decay-time 1

########################### ACTIVE DEFRAGMENTATION #######################
#
# 开启自动内存碎片整理(总开关)
# 警告此功能是实验性的。然而,即使在生产中也进行了压力测试,并且由多个工程师手动测试了一段时间。
# 什么是主动碎片整理?
# -------------------------------
# 自动(实时)碎片整理允许Redis服务器压缩内存中小数据分配和数据释放之间的空间,从而允许回收内存。
# 
# 碎片化是每个分配器都会发生的一个自然过程(幸运的是,对于Jemalloc来说却不那么重要)和某些工作负载。
# 通常需要重新启动服务器以降低碎片,或者至少刷新所有数据并再次创建。
# 但是,由于Oran Agra为Redis 4.0实现了这一功能,这个过程可以在运行时以“热”的方式发生,而服务器正在运行。
# 
# 基本上当碎片超过一定水平时(参见下面的配置选项),
# Redis将开始通过利用某些特定的Jemalloc功能在相邻的内存区域中创建值的新副本(以便了解分配是否导致碎片并分配它在一个更好的地方),
# 同时,将释放数据的旧副本。对于所有键,以递增方式重复此过程将导致碎片回退到正常值。
#
# 需要了解的重要事项:
# 1.默认情况下,此功能处于禁用状态,仅在您编译Redis以使用我们随Redis源代码提供的Jemalloc副本时才有效。这是Linux版本的默认设置。
# 2.如果没有碎片问题,则永远不需要启用此功能。
# 3.一旦遇到碎片,可以在需要时使用命令“CONFIG SET activedefrag yes”启用此功能。
# 配置参数能够微调其行为碎片整理过程。如果您不确定它们的含义,最好保持默认设置不变。
#
# activedefrag no

# 当碎片达到 100mb 时,开启内存碎片整理
#
# active-defrag-ignore-bytes 100mb

# 当碎片超过 10% 时,开启内存碎片整理
#
# active-defrag-threshold-lower 10

# 内存碎片超过 100%,则尽最大努力整理
#
# active-defrag-threshold-upper 100

# 内存自动整理占用资源最小百分比
#
# active-defrag-cycle-min 1

# 内存自动整理占用资源最大百分比
#
# active-defrag-cycle-max 25

# 主字典扫描将处理的set/hash/zset/list字段的最大数目
#
# active-defrag-max-scan-fields 1000

# 默认情况下,用于清除的Jemalloc后台线程是启用的。
jemalloc-bg-thread yes

# 设置redis服务器/io线程的cpu亲和力0,2,4,6:
# server_cpulist 0-7:2
#
# 将bio线程设置为cpu亲和力1,3:
# bio_cpulist 1,3
#
# 设置aof重写子进程为cpu亲和力8、9、10、11:
# aof_rewrite_cpulist 8-11
#
# 将bgsave子进程设置为cpu亲缘关系1,10,11
# bgsave_cpulist 1,10-11

Redis持久化

Redis提供了将内存数据持久化到硬盘,以及用持久化文件来恢复数据库数据的功能。Redis 支持两种形式的持久化,一种是RDB快照(snapshotting),另外一种是AOF(append-only-file);最后一种是两种结合的混合模式

1.RDB快照(snapshot)

介绍
RDB是Redis用来进行持久化的一种方式,RDB是通过保存数据库中的键值对来记录数据库的状态;把当前内存中的数据集快照写入磁盘,也就是 Snapshot 快照(数据库中所有键值对数据)。在默认情况下, Redis 将内存数据库快照保存在名字为 dump.rdb 的二进制文件中。恢复时是将快照文件直接读到内存里。

你可以对 Redis 进行设置, 让它在“ N 秒内数据集至少有 M 个改动”这一条件被满足时, 自动保存一次数据集。比如说, 以下设置会让 Redis 在满足“ 60 秒内有至少有 1000 个键被改动”这一条件时, 自动保存一次数据集:

save 60 1000

关闭RDB只需要将所有的save保存策略注释掉即可,或者redis.conf只配置save "";还可以在客户端通过命令redis-cli config set save " "来进行关闭。

redis.conf中RDB的相关配置

redis 32 绿色下载 redis6.2.0_redis 32 绿色下载_02


触发方式

  • 1、自动触发
  • redis.conf配置save;
  • 在主从复制场景下,如果从节点执行全量复制操作,则主节点会执行 bgsave 命令,并将rdb文件发送给从节点;执行shutdown命令时,自动执行rdb持久化
  • 2、手动触发
  • save:该命令会阻塞当前Redis服务器,执行save命令期间,Redis不能处理其他命令,直到RDB过程完成为止。显然该命令对于内存比较大的实例会造成长时间阻塞,这是致命的缺陷,为了解决此问题,Redis提供了第二种方式。
  • bgsave:执行该命令时,Redis会在后台异步进行快照操作,快照同时还可以响应客户端请求。具体操作是Redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束。阻塞只发生在fork阶段,一般时间很短。该命令会有一个[schedule]参数,设置触发时间

save m n:实现原理

  • 1、Redis的save m n,是通过serverCron函数、dirty计数器、和lastsave时间戳来实现的。
  • 2、serverCron是Redis服务器的周期性操作函数,默认每隔100ms执行一次(可在redis.conf 文件中配置 默认:hz 10 这个配置表示1s内执行10次,也就是每100ms触发一次定时任务);该函数对服务器的状态进行维护,其中一项工作就是检查 save m n 配置的条件是否满足,如果满足就执行 bgsave。
  • 3、dirty计数器是Redis服务器维持的一个状态,记录了上一次执行bgsave/save命令后,服务器状态进行了多少次修改(包括增删改);而当save/bgsave执行完成后,会将dirty重新置为0。
  • 4、例如,如果Redis执行了set mykey helloworld,则dirty值会+1;如果执行了sadd myset v1 v2 v3,则dirty值会+3;注意dirty记录的是服务器进行了多少次修改,而不是客户端执行了多少修改数据的命令。
  • 5、lastsave时间戳也是Redis服务器维持的一个状态,记录的是上一次成功执行save/bgsave的时间。
  • 6、save m n的原理如下:每隔100ms,执行serverCron函数;在serverCron函数中,遍历save m n配置的保存条件,只要有一个条件满足,就进行bgsave。
  • 7、所以save最终也是执行的bgsave

对于每一个save m n条件,只有下面两条同时满足时才算满足:

当前时间-lastsave > m
dirty >= n

save与bgsave比对

命令

save

bgsave

IO类型

同步

异步

是否阻塞redis其它命令


否(在生成子进程执行调用fork函数时会有短暂阻塞)

复杂度

O(n)

O(n)

优点

不会消耗额外内存

不阻塞客户端命令

缺点

阻塞客户端命令

需要fork子进程,消耗内存

总结
save:   优点:节约系统资源
  缺点:直接调用 rdbSave ,阻塞 Redis 主进程,直到保存完成为止。在主进程阻塞期间,服务器不能处理客户端的任何请求。
bgsave:   优点:fork 出一个子进程,子进程负责调用 rdbSave ,并在保存完成之后向主进程发送信号,通知保存已完成。 Redis 服务器在BGSAVE 执行期间仍然可以继续处理客户端的请求
  缺点:由于会fork一个进程,因此更消耗内存
综上:   还是推荐使用bgsave命令,毕竟save命令阻塞其他请求是我们无法接受的

优缺点
优点

  • 1、RDB是一个非常紧凑(compact)的文件,它保存了redis 在某个时间点上的数据集。这种文件非常适合用于进行备份和灾难恢复
  • 2、生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作
  • 3、RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快

缺点

  • 1、RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,属于重量级操作(内存中的数据被克隆了一份,大致2倍的膨胀性需要考虑),频繁执行成本过高(影响性能)
  • 2、RDB文件使用特定二进制格式保存,Redis版本演进过程中有多个格式的RDB版本,存在老版本Redis服务无法兼容新版RDB格式的问题(版本不兼容)
  • 3、在一定间隔时间做一次备份,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改(数据有丢失)
2.AOF(append-only file)

介绍
AOF 则是通过保存Redis服务器所执行的写命令来记录数据库状态。AOF是一种完全耐久的持久化方式: AOF 持久化,将修改的每一条指令记录进文件appendonly.aof中
比如对于如下命令:

127.0.0.1:6379> set str1 "1"
OK
127.0.0.1:6379> sadd str2 "1" "2" "3"
(integer) 1
127.0.0.1:6379> lpush str3 "1" "2" "3"
(integer) 3

RDB 持久化方式就是将 str1,str2,str3 这三个键值对保存到 RDB文件中,而 AOF 持久化则是将执行的set,sadd,lpush 三个命令保存到 AOF 文件中。

redis.conf中AOF的相关配置

redis 32 绿色下载 redis6.2.0_redis_03


开启AOF

将 redis.conf 的 appendonly 配置改为 yes 即可。

appendonly yes

AOF 保存文件的位置和 RDB 保存文件的位置一样,都是通过 redis.conf 配置文件的 dir 配置;在客户端控台可以通过 config get dir 命令获取保存的路径。

AOF重写
由于AOF持久化是Redis不断将写命令记录到 AOF 文件中,随着Redis不断的进行,AOF 的文件会越来越大,文件越大,占用服务器内存越大以及 AOF 恢复要求时间越长。为了解决这个问题,Redis新增了重写机制,当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。可以使用命令bgrewriteaof 来重写。

如下命令

127.0.0.1:6379> sadd names zs
(integer) 1
127.0.0.1:6379> sadd names ls
(integer) 1
127.0.0.1:6379> sadd names ww
(integer) 1

如果不进行 AOF 文件重写,那么 AOF 文件将保存四条 SADD 命令,如果使用AOF 重写,那么AOF 文件中将只会保留下面一条命令:

sadd names zs ls ww

AOF重写机制
AOF 文件重写并不是对原文件进行重新整理,而是直接读取服务器现有的键值对,然后用一条命令去代替之前记录这个键值对的多条命令,生成一个新的文件后去替换原来的 AOF 文件。

AOF 文件重写触发机制: 通过 redis.conf 配置文件中的 auto-aof-rewrite-percentage:默认值为100,以及auto-aof-rewrite-min-size:64mb 配置,也就是说默认Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发。

Redis 是单线程工作,如果 重写 AOF 需要比较长的时间,那么在重写 AOF 期间,Redis将长时间无法处理其他的命令,这显然是不能忍受的。Redis为了克服这个问题,解决办法是将 AOF 重写程序放到子程序中进行,这样有两个好处:
   + 子进程进行 AOF 重写期间,服务器进程(父进程)可以继续处理其他命令。
   + 子进程带有父进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性。

使用子进程解决了上面的问题,但是新问题也产生了:因为子进程在进行 AOF 重写期间,服务器进程依然在处理其它命令,这新的命令有可能也对数据库进行了修改操作,使得当前数据库状态和重写后的 AOF 文件状态不一致。
为了解决这个数据状态不一致的问题,Redis 服务器设置了一个 AOF 重写缓冲区,这个缓冲区是在创建子进程后开始使用,当Redis服务器执行一个写命令之后,就会将这个写命令也发送到 AOF 重写缓冲区。当子进程完成 AOF 重写之后,就会给父进程发送一个信号,父进程接收此信号后,就会调用函数将 AOF 重写缓冲区的内容都写到新的 AOF 文件中。
这样将 AOF 重写对服务器造成的影响降到了最低。

优缺点
优点

  • 1、AOF 持久化的方法提供了多种的同步频率,即使使用默认的同步频率每秒同步一次,Redis 最多也就丢失 1 秒的数据而已
  • 2、AOF 文件使用 Redis 命令追加的形式来构造,因此,即使 Redis 只能向 AOF 文件写入命令的片断,使用 redis-check-aof 工具也很容易修正 AOF 文件
  • 3、AOF 文件的格式可读性较强,这也为使用者提供了更灵活的处理方式。例如,如果我们不小心错用了 FLUSHALL 命令(Flushall 命令用于清空整个 Redis 服务器的数据(删除所有数据库的所有 key )),在重写还没进行时,我们可以手工将最后的 FLUSHALL 命令去掉,然后再使用 AOF 来恢复数据

缺点

  • 1、对于具有相同数据的的 Redis,AOF 文件通常会比 RDB 文件体积更大
  • 2、虽然 AOF 提供了多种同步的频率,默认情况下,每秒同步一次的频率也具有较高的性能。但在 Redis 的负载较高时,RDB 比 AOF 具好更好的性能保证
  • 3、RDB 使用快照的形式来持久化整个 Redis 数据,而 AOF 只是将每次执行的命令追加到 AOF 文件中,因此从理论上说,RDB 比 AOF 方式更健壮。官方文档也指出,AOF 的确也存在一些 BUG,这些 BUG 在 RDB 没有存在
RDB和AOF对比

命令

RDB

AOF

启动优先级



体积



恢复速度



数据安全性

容易丢失数据

根据策略决定

redis启动时如果既有rdb文件又有aof文件则优先选择aof文件恢复数据,因为aof一般来说数据更全一点。

3.混合持久化(RDB+AOF)

介绍
重启 Redis 时,我们很少使用 rdb 来恢复内存状态,因为会丢失大量数据。

如果使用 AOF 日志重放,性能则相对 rdb 来说要慢很多,这样在 Redis 实例很大的情况下,启动的时候需要花费很长的时间。

Redis 4.0 + 为了解决这个问题,带来了一个新的持久化选项——混合持久化。

混合持久化同样也是通过bgrewriteaof完成的,不同的是当开启混合持久化时,fork出的子进程先将共享的内存副本全量的以RDB方式写入aof文件,然后在将aof_rewrite_buf重写缓冲区的增量命令以AOF方式写入到文件,写入完成后通知主进程更新统计信息,并将新的含有RDB格式和AOF格式的AOF文件替换旧的的AOF文件。简单的说:新的AOF文件前半段是RDB格式的全量数据后半段是AOF格式的增量数据。

在redis重启的时候,加载 aof 文件进行恢复数据:先加载 rdb 内容再加载剩余的 aof

开启混合持久化模式
将 redis.conf 的 aof-use-rdb-preamble 配置改为 yes 即可。

aof-use-rdb-preamble yes

混合持久化AOF文件结构

redis 32 绿色下载 redis6.2.0_Redis_04