1、redis提供给缓存数据设置过期时间的功能有什么用?
命令:expire key seconds 设置过期时间、ttl key 查看过期时间、persist key 移除过期时间 可以及时清理不用的数据,缓解内存压力; 简化某些定时清理场景的设置,例如验证码、登录的token等。 使用传统数据库,需要自己判断过期,并且性能较差,例如mysql创建事件和存储过程定时清理表数据: MYSQL:指定时间删除过期数据 redis把所有键的过期时间存储在redisDb结构的 expires字典中(哈希表),该字典的键存储redis数据的key,该字典的值存储数据key对应的过期时间,过期字典的值是一个long long类型的整数。
typedef struct redisDb {
...
dict *dict; //数据库键空间,保存着数据库中所有键值对
dict *expires // 过期字典,保存着键的过期时间
...
} redisDb;
2、redis的过期数据删除策略?
定期删除 + 惰性删除 定期删除是指定期抽取一部分key进行过期检查,执行过期key的删除操作,redis底层通过限制删除操作的时长和频率来减少定期删除对cpu使用效率的影响。 惰性删除是指只有在取出key的时候才会进行过期检查,可能会存在大量过期的key未被删除。 定期删除对内存更加友好,惰性删除对cpu更加友好。
经过定期删除和惰性删除,仍然可能存在被遗漏的过期的key,导致这些过期的key堆积在内存,导致oom。缓解这个问题的方案就是:Redis内存淘汰机制。
3、redis的内存淘汰机制?
用来保证redis中的数据都是热点数据,或者当内存不足时,为新写入的数据提供空间。 volatile指设置了过期时间的key,allkeys指所有的key。 volatile-lru(least recently used) 从设置了过期时间的数据中(server.db[i].expires) 淘汰最近最少被使用的数据。 volatile-random 从设置了过期时间的数据中 随机淘汰数据。 volatile-lfu 从设置了过期时间的数据中 淘汰最不频繁被使用的数据。
allkeys-lru 从所有的数据中(server.db[i].dict) 淘汰最近最少被使用的数据。- 常用 allkeys-random 从所有的数据中(server.db[i].dict)随机淘汰数据。 allkeys-lfu 从所有的数据中(server.db[i].dict)淘汰最不频繁被使用的数据。
volatile-ttl 从设置了过期时间的数据中(server.db[i].expires)淘汰将要过期的数据。 no-eviction 禁止淘汰数据。
4、redis的持久化机制
为什么需要持久化?
因为redis是内存数据库,一旦服务器退出(故障、意外退出等),内存中保存的数据就会丢失,为了在服务器重启时能够快速恢复redis中的数据,需要将内存中的数据持久化到磁盘中(一个远程位置),重启时从磁盘中读入内存。
redis中的持久化方式?
RDB(快照 snapshotting) AOF(只追加文件 append-only file) 混合持久化
什么是RDB持久化?
RDB持久化是redis默认的持久化方式,RDB 持久化是通过快照(snapshotting)完成的,将内存中的数据进行快照并持久化到硬盘,保存的是数据的映射。 RDB持久化将某个时间点上Redis中的数据保存到一个RDB文件中。该文件是一个经过压缩的二进制文件,通过该文件可以还原生成RDB文件时Redis中的数据。 都在说快照,但快照到底是什么?:快照是数据库在拷贝点的静态映像。 Redis的快照 :把内存中的redis数据的映像保存到RDB文件中。
如何创建RDB文件,或者说触发快照?
可以在命令行输入SAVE 或者 BGSAVE命令;
二者的区别是: SAVE命令(阻塞式命令)会阻塞Redis服务器进程,直到RDB文件创建完毕为止,在服务器进程阻塞期间,服务器不能处理任何命令请求。 BGSAVE命令(非阻塞式命令)会fork一个子进程,然后由子进程负责创建RDB文件,redis服务器进程(父进程)继续处理命令请求。 因为BGSAVE命令可以在不阻塞服务器进程的情况下执行,所以推荐使用BGSAVE命令。
或者在配置文件中设置快照的触发规则,RDB文件的名称、保存路径,是否压缩、加载时是否检查完整性等。通常启动redis容器时,会将redis容器的conf文件和data目录挂载到服务器磁盘中。(data目录是redis的工作目录?)
################################ SNAPSHOTTING ################################
# Save the DB on disk:
# save <seconds> <changes>
# Will save the DB if both the given number of seconds and the given
# number of write operations against the DB occurred.
# In the example below the behavior will be to save:
# after 900 sec (15 min) if at least 1 key changed
# after 300 sec (5 min) if at least 10 keys changed
# after 60 sec if at least 10000 keys changed
save 900 1
save 300 10
save 60 10000
# The filename where to dump the DB
dbfilename dump.rdb
# The working directory.
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
# The Append Only File will also be created inside this directory.
# Note that you must specify a directory here, not a file name.
dir ./
推荐设置Redis服务器的配置文件。上述设置了BGSAVE命令的触发条件,rdb文件名(dump.rdb),保存位置(./)。
如何通过载入RDB文件恢复数据?
无操作命令,redis服务器重启时自动载入,并且服务器在载入RDB文件期间,会一直处于阻塞状态,直到RDB文件载入成功。 但是,Redis服务器启动时是否会载入RDB文件来还原数据 需要判断服务器是否启用了AOF持久化功能,逻辑如下: 如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据。 只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据。 注:默认情况下,Redis服务器的AOF持久化功能是关闭的,RDB是默认的持久化方式。
什么是AOF持久化?
通过保存redis服务器中执行的写命令到AOF文件中,来记录数据库中的数据。
如何实现AOF持久化?
需要在配置文件中设置AOF开启、aof文件名、将服务器操作同步到aof文件的频率。 Redis服务器在执行完一个写命令之后,会将被执行的写命令追加到服务器状态的AOF缓冲区的末尾,然后Redis服务器会根据配置文件中appendfsync选项设置的同步频率来决定何时将AOF缓冲区中的内容同步到AOF文件里面。
推荐使用everysecond模式,实现了性能和安全性的折中。
############################## APPEND ONLY MODE ###############################
# By default Redis asynchronously dumps the dataset on disk. This mode is
# good enough in many applications, but an issue with the Redis process or
# a power outage may result into a few minutes of writes lost (depending on
# the configured save points).
#
# The Append Only File is an alternative persistence mode that provides
# much better durability. For instance using the default data fsync policy
# (see later in the config file) Redis can lose just one second of writes in a
# dramatic event like a server power outage, or a single write if something
# wrong with the Redis process itself happens, but the operating system is
# still running correctly.
#
# AOF and RDB persistence can be enabled at the same time without problems.
# If the AOF is enabled on startup Redis will load the AOF, that is the file
# with the better durability guarantees.
appendonly yes
# The name of the append only file (default: "appendonly.aof")
appendfilename "appendonly.aof"
# Redis supports three different modes:
#
# no: don't fsync, just let the OS flush the data when it wants. Faster.让操作系统决定何时进行同步。
# always: fsync after every write to the append only log. Slow, Safest.每次有数据修改时,都会写入AOF文件。
# everysec: fsync only one time every second. Compromise.每秒同步一次。
#
# The default is "everysec", as that's usually the right compromise between
# speed and data safety. It's up to you to understand if you can relax this to
# "no" that will let the operating system flush the output buffer when
# it wants, for better performances (but if you can live with the idea of
# some data loss consider the default persistence mode that's snapshotting),
# or on the contrary, use "always" that's very slow but a bit safer than
# everysec.
#
# If unsure, use "everysec".
# appendfsync always
appendfsync everysec
# appendfsync no
如何通过载入AOF文件恢复数据?
因为AOF文件包含了重建数据库所需的所有写命令,所以Redis服务器只要读入并重新执行一遍AOF文件里面保存的写命令,就可以还原Redis服务器关闭之前的数据。 流程:创建伪客户端 -> 从AOF中读入一条写命令 -> 执行该写命令(循环 直至所有写命令都被执行)->执行完毕
什么是AOF重写?
随着Redis服务器运行时间的增加,AOF文件的体积会越来越大,并且在操作数据库创建数据时存在很多冗余的命令,如果不做控制,会过多的占用服务器磁盘空间,使用AOF文件来进行数据库还原时所需的时间就越多。 为了解决AOF文件体积越来越大的问题,Redis提供了AOF文件重写功能,即Redis服务器会创建一个新的AOF文件来替代现有的AOF文件,新旧两个AOF文件所保存的数据库数据相同,但新AOF文件不会包含任何浪费空间的冗余命令,所以新AOF文件的体积通常会比旧AOF文件的体积要小很多。
AOF重写的实现原理?
AOF文件重写并不需要对现有的AOF文件进行任何读取、分析或者写入操作,而是通过读取数据库中的数据(键值对)来实现的。AOF重写生成的新AOF文件就会减少很多冗余命令,进而大大减小了AOF文件的体积。 实现过程:从数据库中读取键对应的值,用一条命令记录键值对,代替之前的多条冗余命令。
AOF后台重写的实现过程?
后台重写的两种设置方式: 手动执行BGREWRITEAOF命令; 在配置文件中设置自动执行BGREWRITEAOF命令的配置项。
# Automatic rewrite of the append only file.
# Redis is able to automatically rewrite the log file implicitly calling
# BGREWRITEAOF when the AOF log size grows by the specified percentage.
#
# This is how it works: Redis remembers the size of the AOF file after the
# latest rewrite (if no rewrite has happened since the restart, the size of
# the AOF at startup is used).
#
# This base size is compared to the current size. If the current size is
# bigger than the specified percentage, the rewrite is triggered. Also
# you need to specify a minimal size for the AOF file to be rewritten, this
# is useful to avoid rewriting the AOF file even if the percentage increase
# is reached but it is still pretty small.
#
# Specify a percentage of zero in order to disable the automatic AOF
# rewrite feature.
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
该配置表示:首次触发BGREWRITEAOF命令的AOF文件最小体积是64MB;并且当AOF文件的体积比上一次重写之后的体积增大一倍时(100%),Redis将再次自动执行BGREWRITEAOF命令。
AOF后台重写的实现过程: 服务器进程创建AOF重写子进程,子进程开始AOF文件重写; 从创建子进程开始,服务器进程执行的所有写命令不仅要写入AOF缓冲区,还要写入AOF重写缓冲区; 子进程完成AOF重写工作,创建了一个新的AOF文件,同时向父进程发送一个信号,父进程在接收到该信号后,会执行以下操作: 将AOF重写缓冲区中的所有内容写入到新AOF文件中,这样就保证了新AOF文件所保存的数据库数据和服务器当前的数据库数据是一致的。 对新的AOF文件进行改名,覆盖现有的AOF文件,完成新旧两个AOF文件的替换。
为什么需要AOF重写缓冲区:
AOF缓冲区将服务器执行的命令同步到原有的AOF文件。 AOF重写缓冲区是为了保存子进程在进行AOF文件重写期间服务器进程执行的命令,在重写完成后同步到新的AOF文件中。
利用子进程实现AOF重写的好处: 防止主进程在AOF重写时阻塞,有了子进程,服务器进程(父进程)可以继续处理命令请求; 子进程带有服务器进程的数据副本,使用子进程而不是线程,可以在避免使用锁的情况下,保证数据的安全性。 子进程和父进程资源共享关系
RDB和AOF持久化方式的对比?
实现方式:RDB持久化是将某一时间节点的数据库数据快照保存到RDB文件;AOF持久化是将服务器中执行过的写命令保存到AOF文件中。一个保存的是数据,一个保存的是命令。 安全性:AOF(appendfsync = everysecond)每秒同步一次AOF缓冲区和AOF文件,触发快照(同步RDB文件)的间隔往往超过一秒,因此AOF持久化的安全性更好。 优先级:如果开启了AOF持久化功能,在还原数据时,AOF优先级高于RDB,主要考虑到数据安全性。
RDB和AOF持久化方式的优缺?
RDB:
优点: RDB文件小(二进制文件),非常适合定时备份,用于灾难恢复 Redis加载RDB文件的速度比AOF快很多,因为RDB文件中直接存储的是内存数据。 缺点 RDB无法做到实时持久化,若在两次BGSAVE间宕机,则会丢失区间(分钟级)的增量数据,不适用于实时性要求较高的场景 RDB的cow机制中,fork子进程属于重量级操作
AOF:
优点: 1s同步一次,安全性高。 AOF只是追加写日志文件,对服务器性能影响较小,速度比RDB要快,消耗的内存较少。 缺点: AOF方式生成的日志文件太大,需要不断AOF重写,消耗资源。即使经过AOF重写,由于文件是文本文件,文件体积较大(相比于RDB的二进制文件)。 AOF文件用于恢复数据时需要逐条执行命令,速度比RDB慢。
RDB和AOF的混合持久化机制?
Redis持久化之混合持久化 在配置文件中设置开启:
# When rewriting the AOF file, Redis is able to use an RDB preamble in the
# AOF file for faster rewrites and recoveries. When this option is turned
# on the rewritten AOF file is composed of two different stanzas:
#
# [RDB file][AOF tail]
#
# When loading, Redis recognizes that the AOF file starts with the "REDIS"
# string and loads the prefixed RDB file, then continues loading the AOF
# tail.
aof-use-rdb-preamble yes
混合持久化是通过aof的bgrewriteaof命令(AOF重写命令)完成的。 当开启混合持久化时,fork出的重写子进程先将共享的内存全量数据(RDB文件)以RDB方式写入aof文件,然后再将AOF重写缓冲区的增量命令以AOF方式写入到AOF文件,写入完成后通知主进程更新统计信息,并将新的含有RDB格式和AOF格式的AOF文件替换旧的的AOF文件。 简单的说:新的AOF文件前半段是RDB格式的全量数据后半段是AOF格式的增量数据。
在redis重启的时候,加载AOF文件进行恢复数据:先加载RDB内容再加载剩余的AOF。
优点: 重写AOF文件、利用AOF文件恢复数据时 速度加快。
参考: javaguide 熟悉Redis?讲讲你理解的Redis的持久化机制(RDB、AOF) Redis的持久化机制
|