数据人与超自然意识 发表于 2024-6-11 19:19:07

关于Redis的持久化

Redis与MySQL的不同

MySQL的事务,有四个焦点特性:原子性、一致性、持久性和隔离性
   把数据存储在磁盘上就是持久化的,把数据存储在内存上则是不持久化的。区别在于重启进程/主机后,数据是否存在。
而Redis是一个内存数据库,是把数据存储在内存中的!!!
而相较于MySQL,Redis最大的上风就是快、效率高
但是如果要保证数据的持久化,就必须要把数据写入磁盘,但又不能破坏掉Redis的高效,以是Redis采取以下策略:


[*] 插入一个新数据的时间,需要把这份数据同时写入内存和磁盘
[*] 查询某个数据的时间,直接从内存中读取
[*] 硬盘中的数据只是在Redis重启的时间,用来恢复内存中的数据的
这样做的代价就是消耗了更多的空间,但是硬盘比较自制,这样的开销并不会带来太多本钱。
题目在于,Redis查询数据时访问内存,效率确实快很多,但是插入数据时,既要写内存又要写硬盘,多了IO操纵,该怎么保证效率?
Redis持久化的策略

RDB(Redis DataBase) 定期备份

定期地把Redis内存中的所有数据,都写入硬盘中,天生一个“快照”,后续Redis一旦重启,就可以根据快照恢复内存数据
手动触发

步伐员通过Redis客户端,执行特定的命令(save、bgsave),触发天生快照


[*] save命令在前台进行,执行时会全力以赴地进行天生快照的操纵,会壅闭其他的客户端命令,造成类似于keys*的效果
[*] bgsave在后台进行,并不影响其他客户端请求,注意这里是采取多进程的方式完成并发编程,Redis中没有多线程
bgsave的工作流程:
当父进程也就是Redis服务器收到一个bgsave的命令,会先判定当前是否已经存在其他正在工作的子进程,如果当前已经有一个子进程在执行bgsave,就直接把当前的bgsave命令返回,否则就创建一个子进程执行bgsave,也就是Redis中任何时间只能有一个客户端执行bgsave。子进程完成整体的持久化过程之后,会关照父进程,父进程进行一些统计信息的更新,随后烧毁子进程。
执行RDB会天生一个镜像文件dump.rdb,把内存中的数据以压缩的情势生存到该二进制文件中,固然需要消耗肯定的CPU资源,但是可以节省存储空间
RDB持久化操纵是可以触发多次的,在已经存在dump.rdb 文件的环境下再进行rdb操纵,会先把要天生的快照数据生存在一个临时文件中,快照天生完毕后会删除之前的rdb文件,再把临时文件名称改为dump.rdb,自始至终都只有一个dump.rdb文件
自动触发

在Redis设置文件中,设置让Redis每隔多长时间/每产生多少次修改就触发天生快照
但由于天生快照的操纵不能太频繁,以是快照数据和实时数据可能会存在毛病,以是在不满足天生快照条件的时间,如果Redis服务器挂了,就会导致一部分数据丢失
但是Redis的自动触发天生快照不仅可以通过设置文件的方式,还可以通过Redis的shutdown命令触发,当Redis进行主从复制的时间,主节点也会自动天生rdb快照,然后把rdb快照文件内容传输给从节点。
注意,如果是通过正常流程重新启动Redis服务器,此时Redis服务器会在提出的时间,自动触发天生rdb操纵,但如果是非常重启(kill -9 或者 服务器掉电),服务器就来不及天生rdb,此时内存中尚未生存到快照中的数据就会丢失
总结:


[*] Redis采取rdb天生快照的操纵要对内存中所有数据进行生存,以是实用于全量数据生存的环境
[*] 由于rdb操纵最终生存的二进制,以是加载数据时要快于AOF(用文本的情势生存)
[*] RDB方式没有办法做到实时持久化/秒级持久化,由于bgsave每次执行都要执行fork创建子进程,属于重量级操纵,频繁操纵本钱过高
[*] RDB文件利用二进制格式生存,Redis版本演进过程中会有多个RDB版本,兼容性可能会有风险
RDB最大的题目就是,不能实时的持久化生存数据,在两次天生快照之间,实时的数据可能会随着重启而丢失。
AOF(Append Only File) 实时备份

AOF的生存数据方式类似于MySQL中的 binlog,会把用户的每个操纵,记录在文件中,当Redis重启的时间,就会读取这个aof文件中的内容,用来恢复数据(当开启aof的时间,就默认rdb失效,不再读取rdb文件中的内容)
照旧和RDB同样的题目,Redis把操纵写进aof文件,又要写内存,又要写磁盘,怎么保证速率?

[*] AOF机制并非是直接让工作线程把数据写入硬盘,而是先写入一个内存中的缓冲区,积聚到肯定量之后,再同一写进硬盘
[*] AOF每次都会把新的操纵写到原有文件内容的末尾,属于次序写入,硬盘上读写数据,次序读写的速率比随机要快(当然照旧比内存慢)
跟RDB相同,如果在内存缓冲区中的数据量不够革新到磁盘时,出现了服务器掉电的环境,这部分数据就会丢失。以是,针对这个环境,Redis给出了一些选项供步伐员选择(在革新频率和效率之间做一个决议),就像MySQL中的事务隔离级别,安全性和效率往往不能兼顾
Redis的重写机制(rewrite)

对于AOF备份,当操纵越来越多,AOF文件的体积就越来越大,虽说磁盘空间不值钱,但是在Redis重启加载数据的时间会有很大的消耗,而且AOF中很可能有一些数据时冗余的(比如先插入数据,再删除数据,实际上Redis关注的只是数据末了的状态)
以是Redis中有一个机制,可以对AOF文件中的冗余信息进行缩减,告竣“瘦身”的效果,也就是重写机制。
AOF重写和RDB一样也分为手动和自动,大致原理相同,不再赘述。
AOF重写流程:
创建子进程,父进程仍然负责接收请求,子进程负责对AOF文件进行重写,重写过程中不关心原来的AOF文件中的所有操纵记录,只关心当前内存中的数据状态,把当前最新的数据状态以AOF的情势写入一个新文件,把原有的AOF文件删除,再把新文件改为AOF即可
在父进程创建子进程之后,子进程重写之间,父进程可能还会接收到新的请求,这时还会往旧的AOF文件中写入数据,当子进程重写完成后覆盖原有的AOF文件,新写入的数据不就丢失了吗?
为了避免这个环境,Redis的AOF重写机制中,父进程创建完子进程之后,会有另外一个aof_rewrite_buf缓冲区,用于存放fork之后收到的数据。这时父进程收到的新的数据不仅要写入原来的AOF文件,还要写入这个缓冲区,当子进程完成重写之后会通过信号 关照父进程,父进程就会把缓冲区中的内容页写入新的AOF文件中。
特别环境:


[*] 如果在执行bgrewriteaof的时间,发现当前Redis正在进行AOF重写,此时就不会再次执行AOF重写,直接返回
[*] 如果在执行bgrewriteaof的时间,发现当前Redis正在天生rdb快照,此时AOF重写操纵就会等待rdb快照天生完毕之后,再进行AOF重写
这里可以发现,RDB和AOF的不同,RDB对于fork之后的数据,就直接置之不理了,并不会采取rewrite_buf的方式来处理。
RDB自己的设计理念就是用来“定期备份”的,只要是定期备份,就难以和最新的数据保持一致,但定期备份和实时备份没有绝对的谁好谁坏,照旧要看具体的利用场景
既然父进程fork之后,子进程就会往新的AOF文件中写入数据,那么父进程只需要往aof_rewrite_buf中写入数据就行了,为什么还要向旧的AOF文件中写?
思量极端环境,子进程重写AOF过程中,服务器挂了,子进程内存中的数据就会丢失,新的AOF文件内容还不完整,这时需要父进程中旧的AOF文件保证数据的完整性。
但是,AOF文件并不是任何时间都只有文本范例的数据,可能还包含二进制数据。由于文本的方式写文件,后续的加载本钱比较高。于是,Redis引入了“混淆持久化”的方式,结合了rdb 和 aof 的特点。针对每一个请求/操纵,按照AOF的方式记录进文件;在触发AOF重写之后,会把当前内存中的状态按照RDB的二进制格式写入新的AOF文件中;后续有新的操纵,仍然是按照AOF文本的方式追加到文件后面。
当Redis中同时存在AOF文件和RDB快照的时间,以AOF为主,RDB直接忽略,由于AOF中的数据更全

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 关于Redis的持久化