redis 数据持久化

一、redis简介

1、Redis,全称是远程数据服务(Remote Dictionary Server)

  它作为一款由 C 语言编写的内存高速缓存数据库,在互联网产品中应用甚广。很多云服务提供商还以 Redis 为基础构建了相应的缓存服务、消息队列服务以及内存存储服务,当你使用这些服务时,实际上就是在使用 Redis。

2、Redis 所有的操作都是内存操作吗?

  并不是,redis 的单线程是指在接收客户端 IO 请求进行读写时是单线程操作。但 redis 本身是存在多线程使用场景的,比如:异步删除,持久化以及集群同步。

3、Redis 常见的持久化机制有哪些
  RDB 和 AOF

 

二、持久化之RDB

1、快照持久化:也叫RDB持久化。就是通过拍摄快照的方式来实现持久化(全量备份),将某个时间的内存数据存储在一个rdb文件中。在redis服务重新启动的时候会加载rdb文件中的数据。

redis中的快照持久化默认是开启的,在redis.conf配置文件中有相关的配置选项。

2、保存快照

save手动触发

  在redis运行中,我们可以显示的发送一条save命令来拍摄快照。save命令是阻塞命令,也就是当服务器接收了一条save命令之后就会开始拍摄快照,在此期间不会再去处理其他的请求,其他请求会被挂起直到备份结束

bgsave自动触发

bgsave命令也是立即拍摄快照,有别于save命令,bgsave并不是一条阻塞命令,而是fork一个子线程,然后这个子线程负责备份操作。而父进程继续处理客户端的请求,这样就不会造成阻塞了。

由配置文件来完成,自动触发 BGSAVE命令,在redis.conf配置文件中有如下配置:

save 900 1 /*900秒内至少发生1次key变换*/

save 60 10 /*60秒内至少发生10次key变换*/

dbfilename dump.rdb /*快照文件名*/

dir ./ /*快照文件存放目录*/

rdbcompression yes /*是否压缩*/

参数

默认值

说明

save

900 1

900秒内至少有1个key被更改就执行快照

save

300 10

300内描述至少有10个key被更改就执行快照

save

60 10000

60秒内至少有10000个key被更改就执行快照

stop-writes-on-bgsave-error

yes

拍摄快照失败是否继续执行写命令

rdbcompression

yes

是否对快照文件进行压缩

rdbchecksum

yes

是否数据校验

dbfilename

dump.rdb

快照文件存储的名称

dir

./

快照文件存储的位置

 

3、优缺点

在 RDB 持久化的时候,Redis fock 子进程会把 Redis 的所有数据都保存到新建的 dump.rdb 文件中,这是一个既消耗资源又浪费时间的操作。因此,Redis 服务器不能过于频繁地创建 rdb 文件,否则会严重影响服务器的性能。

除此之外,RDB 持久化的最大不足之处在于:最后一次持久化的过程中可能会出现大量的数据丢失。我们想象一个场景,在 RDB 进行持久化的过程中,Redis 服务器突然宕机了,这时子进程可能已经生成了 rdb 文件,但是父进程还没来得及用它覆盖掉旧的 rdb 文件,缓冲区中的文件还未保存,就会导致大量数据的丢失。

而 RDB 数据持久化的优势在于它还原速度很快,所以比较适用于大规模的数据恢复,如果对数据的完整性不是特别敏感(允许持久化过程中数据丢失的情况),那么 RDB 持久化方式就非常适合。 

redis命令行获取快照文件

--rdb <filename>  导出rdb文件

redis-cli -h 127.0.0.1 -p 7379  -a  1vqw9qB5Su5  --rdb  /dump.rdb

如何禁用快照持久化

1.在redis.conf配置文件中注释掉所有的save配置 2.在最后一条save配置追加吃命令

save  ""

三、持久化之AOF

1、简介

AOF,append only log file,又被称为追加模式,或日志模式。

AOF 会记录服务器执行的所有写操作命令,并且只记录对内存有过修改的命令,Redis 会将这些命令定时写到 appendonly.aof 文件中。

我们在服务器启动时,可以重新执行 AOF 文件来还原数据集,这个过程被称为命令重演。

RDB机制是全量持久化,效率较低,我们需要一种更加高效的机制AOF,在redis.conf配置文件中有如下配置:

appendonly yes /*开启aof*/

appendfilename "appendonly.aof" /*aof文件名*/

appendfsync always /*一次命令追加一次*/

appendfsync everysec /*每秒追加一次*/

appendfsync no /*从不追加*/

AOF文件:AOF机制将收到的每一个写命令按顺序追加到aof文件中

2、持久化过程

(1)主进程创建子进程,由子进程进行AOF文件的重写操作。

(2)重写期间,如果主进程收到命令,继续追加AOF缓存区,然后定期追加到原AOF文件,现有的AOF文件不受影响。

(3)同时,主进程将命令追加到AOF重写缓存区。

(4)子进程完成重写,向主进程发信号。

(5)主进程将AOF重写缓存区数据追加到新AOF文件。

(6)主进程替换原AOF文件为新AOF文件。

(7)继续接收命令。

3、AOF的三种持久化机制

Redis 在收到客户端修改命令后,会先进行相应的校验,如果命令无误,就立即将该命令存进缓冲区,再以一定的速率将缓冲区数据追加到 .aof 文件中。

这样,就算遇到了突发的宕机情况,也只需将存储到 aof 文件中的命令,进行一次“命令重演”就可以恢复到宕机前的状态。

在上述执行过程中,有一个很重要的环节就是命令的写入,这是一个磁盘 IO 操作:Redis 为了提升写入效率,它不会将内容直接写入到磁盘中,而是先将其放到一个内存缓存区(buffer),等到缓存区被填满或者满足 AOF 的持久化策略时才真正将缓存区中的内容写入到磁盘里(fsync 操作)。

AOF 的持久化策略(即 fsync 操作的频率)分为三种:

  • always:服务器每写入一个命令,就调用一次 fsync 函数,将缓冲区里面的命令写入到硬盘。这种模式下,服务器出现故障,也不会丢失任何已经成功执行的命令数据,但是其执行速度非常慢;
  • everysec(默认):服务器每一秒调用一次 fsync 函数,将缓冲区里面的命令写入到硬盘。这种模式下,服务器出现故障,最多只丢失一秒钟内的执行的命令数据,通常都使用它作为 AOF 配置策略;
  • no:服务器不主动调用 fsync 函数,由操作系统决定何时将缓冲区里面的命令写入到硬盘。这种模式下,服务器遭遇意外停机时,丢失命令的数量是不确定的,所以这种策略,不确定性较大,也不常用。

Redis 在遇到宕机前,如果缓存内的数据未能写入到磁盘中,那么数据仍然会有丢失的风险。而丢失命令的数量,取决于命令被写入磁盘的时间:越早地把命令写入到磁盘中,发生意外时丢失的数据就会越少。

由于是 fsync 是磁盘 IO 操作,所以它很慢!如果 Redis 执行一条指令就要 fsync 一次(always),将会严重地影响到 Redis 的性能。

在生产环境的服务器中,Redis 通常是默认每隔 1s 左右执行一次 fsync 操作( everysec),这样既保持了高性能,也让数据尽可能的少丢失。

而最后一种策略(no),让操作系统来决定何时将数据同步到磁盘,这种策略存在许多不确定性,所以不建议使用。

注:

sync 和 fsync 函数是操作系统提供的两个函数,用来防止“延迟写”造成的缓存和文件的数据不一致问题。

其中,sync 将修改过的数据放入缓存写队列中就返回,不等待 IO 操作结束。

而 fsync 会等待 IO 操作结束再返回,它会确保修改过的块立即写到磁盘上,来保证文件数据和缓存一致。

即,Linux 系统的 fsync() 函数可以将指定文件的内容从内核缓存同步刷新到硬盘中,sync() 是异步操作。

4、重写机制

  在 AOF 的持久化策略下,Redis 在长期运行的过程中,aof 文件会越变越长。而如果机器宕机重启,命令重演整个 aof 文件就会非常耗时,这将导致 Redis 长时间无法对外提供服务。

因此,为了让 aof 文件的大小控制在合理的范围内,Redis 提供了 AOF 重写机制,即对 aof 文件进行 “瘦身” :Redis 服务器可以创建一个新的 AOF 文件来替代现有的 AOF 文件,新旧两个文件所保存的数据库状态是相同的,不同的是新文件没有任务冗余命令,所以文件大小会比旧文件小很多。

  Redis 提供了两种 AOF 文件的重写方式:手动执行 BGREWRITEAOF 命令,或者配置策略实现自动重写。AOF 文件重写时和 RDB 持久化过程类似,都是 fork 一个子进程来操作原 AOF 文件。

   AOF 的重写过程中父进程继续处理新的请求,如果有新的命令添加,会追加到 AOF 重写缓存区,然后直接追加到新的 AOF 文件中。

四、AOF 和 RDB 对比

五、redis配置文件

1.默认情况下,redis不是在后台运行的,如果需要在后台运行,把该项的值更改为yes;

daemonize no

2. 当redis在后台运行的时候,Redis默认会把pid文件放在/var/run/redis.pid,你可以配置到其他地址。当运行多个redis服务时,需要指定不同的pid文件和端口。

pidfile /var/run/redis.pid

3. 指定redis运行的端口

port 6379

4. 设置客户端连接时的超时时间,单位为秒。当客户端在这段时间内没有发出任何指令,那么server端关闭该连接。0为关闭该设置。

timeout 0

5. server日志级别,合法值:debug,verbose,notice,warning 默认为notice

loglevel notice

# debug适合开发环境,客户端操作信息都会输出日志

# erbose输出一些相对有用的信息,目前效果不明

# notice适合生产环境

# warning异常信息

6.指定Redis日志记录方式,默认值为stdout,表示打印在命令行终端的窗口上,也可设为/dev/null屏蔽日志

.logfile

7. 限制同时连接的客户数量。当连接数超过这个值时,redis 将不再接收其他连接请求,客户端尝试连接时将收到 error 信息

maxclients 128

8. 设置redis能够使用的最大内存。达到最大内存设置后,Redis会先尝试清除已到期或即将到期的Key(设置过expire信息的key)在删除时,按照过期时间进行删除,最早将要被过期的key将最先被删除如果已到期或即将到期的key删光,仍进行set操作,那么将返回错误此时redis将不再接收写请求,只接收get请求。maxmemory的设置比较适合于把redis当作于类似memcached 的缓存来使用

maxmemory <bytes>

9. 当内存达到最大值的时候Redis会选择删除哪些数据?有五种方式可供选择

maxmemory-policy

volatile-lru -> 利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used )

# allkeys-lru -> 利用LRU算法移除任何key

# volatile-random -> 移除设置过过期时间的随机key

# allkeys->random -> remove a random key, any key

# volatile-ttl -> 移除即将过期的key(minor TTL)

# noeviction -> 不移除任何可以,只是返回一个写错误

注意:对于上面的策略,如果没有合适的key可以移除,当写的时候Redis会返回一个错误

写命令包括: set setnx setex append

# incr decr rpush lpush rpushx lpushx linsert lset rpoplpush sadd

# sinter sinterstore sunion sunionstore sdiff sdiffstore zadd zincrby

# zunionstore zinterstore hset hsetnx hmset hincrby incrby decrby

# getset mset msetnx exec sort

默认是:

# maxmemory-policy volatile-lru

10. 'syslog-enabled'设置为yes会把日志输出到系统日志,默认是no

syslog-enabled no

11. 指定syslog 设备(facility), 必须是USER或者LOCAL0到LOCAL7

syslog-facility local0

高级配置

1. 当hash中包含超过指定元素个数并且最大的元素没有超过临界时,

# hash将以一种特殊的编码方式(大大减少内存使用)来存储,这里可以设置这两个临界值

# Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现,

# 这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap,

# 当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。

hash-max-zipmap-entries 512
hash-max-zipmap-value 64

2. 是否重置Hash表设置成yes后redis将每100毫秒使用1毫秒CPU时间来对redis的hash表重新hash,可降低内存的使用,当使用场景有较为严格的实时性需求,不能接受Redis时不时的对请求有2毫秒的延迟的话,

把这项配置为no。如果没有这么严格的实时性要求,可以设置为 yes,以便能够尽可能快的释放内存

activerehashing yes

3.list 数据类型多少节点以下会采用去指针的紧凑存储格式。

list 数据类型节点值大小小于多少字节会采用紧凑存储格式。

list-max-ziplist-entries 512
list-max-ziplist-value 64

4. set数据类型内部数据如果全部是数值型,且包含多少节点以下会采用紧凑格式存储。

set-max-intset-entries 512

5. zsort 数据类型多少节点以下会采用去指针的紧凑存储格式。

zsort 数据类型节点值大小小于多少字节会采用紧凑存储格式。

zset-max-ziplist-entries 128
zset-max-ziplist-value 64

SLOWLOG (慢日志)

1. slowlog-log-slower-than 10000

Redis slow log用来记录超过指定执行时间的查询。执行时间不包括I/O计算比如连接客户端,返回结果等,只是命令执行时间可以通过两个参数设置slow log:

一个是告诉Redis执行超过多少时间被记录的参数slowlog-log-slower-than(毫秒),

另一个是slow log 的长度。当一个新命令被记录的时候最早的命令将被从队列中移除负数则关闭slow log,0则会导致每个命令都被记录

2. slowlog-max-len

对日志长度没有限制,只是要注意它会消耗内存可以通过 SLOWLOG RESET 回收被慢日志消耗的内存

protected-mode(有待后续理解)

docker exec -it task_redis bash
redis-cli -h 127.0.0.1 -p 7379

CONFIG SET protected-mode yes
CONFIG SET dir /opt
CONFIG  get dir

bgsave

中的protected-mode在同时存在如下两种情况时触发:

1) The server is not binding explicitly to a set of addresses using the "bind" directive.

2) No password is configured.

六、清除redis缓存

1.访问redis根目录    cd  /usr/local/redis-2.8.19

2.登录redis:redis-cli -h 127.0.0.1 -p 6379

3.查看所有key值:keys *

4.删除指定索引的值:del key

5.清空整个 Redis 服务器的数据:flushall 

6.清空当前库中的所有 key:flushdb

七、redis-cli 命令行

redis-cli [OPTIONS] [cmd [arg [arg ...]]]
选项说明
  -h <hostname>      Server hostname (default: 127.0.0.1). ip地址
  -p <port>          Server port (default: 6379). 服务器端口号
  -s <socket>        Server socket (overrides hostname and port).
  -a <password>      Password to use when connecting to the server. 密码
  -u <uri>           Server URI. url格式的地址
  -r <repeat>        Execute specified command N times.
  -i <interval>      When -r is used, waits <interval> seconds per command.
                     It is possible to specify sub-second times like -i 0.1.
  -n <db>            Database number. 指定数据库
  -x                 Read last argument from STDIN.
  -d <delimiter>     Multi-bulk delimiter in for raw formatting (default: \n).
  -c                 Enable cluster mode (follow -ASK and -MOVED redirections).
  --raw              Use raw formatting for replies (default when STDOUT is
                     not a tty).
  --no-raw           Force formatted output even when STDOUT is not a tty.
  --csv              Output in CSV format.
  --stat             Print rolling stats about server: mem, clients, ... 统计数据 连续输出
  --latency          Enter a special mode continuously sampling latency.
                     If you use this mode in an interactive session it runs
                     forever displaying real-time stats. Otherwise if --raw or
                     --csv is specified, or if you redirect the output to a non
                     TTY, it samples the latency for 1 second (you can use
                     -i to change the interval), then produces a single output
                     and exits. 延时统计
  --latency-history  Like --latency but tracking latency changes over time.
                     Default time interval is 15 sec. Change it using -i.
  --latency-dist     Shows latency as a spectrum, requires xterm 256 colors.
                     Default time interval is 1 sec. Change it using -i.
  --lru-test <keys>  Simulate a cache workload with an 80-20 distribution.
  --replica          Simulate a replica showing commands received from the master.
  --rdb <filename>   Transfer an RDB dump from remote server to local file. 导出rdb文件
  --pipe             Transfer raw Redis protocol from stdin to server.
  管道模式
  --pipe-timeout <n> In --pipe mode, abort with error if after sending all data.
                     no reply is received within <n> seconds.
                     Default timeout: 30. Use 0 to wait forever.
                     管道超时
  --bigkeys          Sample Redis keys looking for big keys.
  --hotkeys          Sample Redis keys looking for hot keys.
                     only works when maxmemory-policy is *lfu.
  --scan             List all keys using the SCAN command.获取服务器所有的键
  --pattern <pat>    Useful with --scan to specify a SCAN pattern.
  正则表达式 用于scan命令中
  --intrinsic-latency <sec> Run a test to measure intrinsic system latency.
                     The test will run for the specified amount of seconds.
  --eval <file>      Send an EVAL command using the Lua script at <file>.
  --ldb              Used with --eval enable the Redis Lua debugger.
  --ldb-sync-mode    Like --ldb but uses the synchronous Lua debugger, in
                     this mode the server is blocked and script changes are
                     not rolled back from the server memory.
  --cluster <command> [args...] [opts...]
                     Cluster Manager command and arguments (see below).
  --verbose          Verbose mode.
  --no-auth-warning  Don't show warning message when using password on command
                     line interface.

server中统计选项

redis-cli --stat
------- data ------ --------------------- load -------------------- - child -
keys       mem      clients blocked requests       connections          
11         835.52K      1       0       12 (+0)             5           
11         835.52K      1       0       13 (+1)             5         
11         835.52K      1       0       14 (+1)             5           
11         835.52K      1       0       15 (+1)             5   

列表中选项说明:

选项含义
keys server中key的数量
mem 键值对的总内存量
clients 当前连接的总clients数量
blocked 当前阻塞的客户端数量
requests 服务器请求总次数 (+1) 截止上次请求增加次数
connections 服务器连接次数

找出server中热点key 命令:redis-cli --hotkeys

# Scanning the entire keyspace to find hot keys as well as
# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec
# per 100 SCAN commands (not usually needed).

[00.00%] Hot key 'dd' found so far with counter 4
[00.00%] Hot key 'myset' found so far with counter 5
[00.00%] Hot key 'a' found so far with counter 5
[00.00%] Hot key 'dds' found so far with counter 4
[71.43%] Hot key 'aa' found so far with counter 4
[71.43%] Hot key 'key' found so far with counter 4

-------- summary -------

Sampled 14 keys in the keyspace!
hot key found with counter: 5	keyname: myset
hot key found with counter: 5	keyname: a
hot key found with counter: 4	keyname: dd
hot key found with counter: 4	keyname: dds
hot key found with counter: 4	keyname: aa
hot key found with counter: 4	keyname: key

八、redis数据存储

redis的存储分为内存存储磁盘存储log文件三部分,配置文件中有三个参数对其进行配置。

save seconds updates,save配置,指出在多长时间内,有多少次更新操作,就将数据同步到数据文件。可多个条件配合,默认配置了三个条件。

appendonly yes/no ,appendonly配置,指出是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。

因为redis本身同步数据文件是按上面的save条件来同步的,所以有的数据会在一段时间内只存在于内存中。

appendfsync no/always/everysec ,appendfsync配置,no表示等操作系统进行数据缓存同步到磁盘,always表示每次更新操作后手动调用fsync()将数据写到磁盘,everysec表示每秒同步一次。

 

 

 

 

 

 

 

 

Redis数据刷盘:来看一看技术行业的缓存神器是如何做的 - 腾讯云开发者社区-腾讯云 (tencent.com) 

Redis 持久化都说不明白?那今天先到这吧~ - 掘金 (juejin.cn)

https://www.jianshu.com/p/d6f1f0724d33  「查缺补漏」巩固你的Redis知识体系

https://www.cnblogs.com/iruxu/p/gitgui.html  Redis 命令参考 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

posted @ 2020-01-11 22:11  凡人半睁眼  阅读(617)  评论(0编辑  收藏  举报