原文连接:深刻学习Redis(2):持久化html
Redis的5种对象类型(字符串、哈希、列表、集合、有序集合)redis
查看内存方法:info memory数据库
内存碎片是Redis在分配、回收物理内存过程当中产生的。例如,若是对数据的更改频繁,并且数据之间的大小相差很大,可能致使redis释放的空间在物理内存中并无释放,但redis又没法有效利用,这就造成了内存碎片。内存碎片不会统计在used_memory中。安全
内存碎片的产生与对数据进行的操做、数据的特色等都有关;此外,与使用的内存分配器也有关系:若是内存分配器设计合理,能够尽量的减小内存碎片的产生。后面将要说到的jemalloc便在控制内存碎片方面作的很好。服务器
解决内存碎片:若是Redis服务器中的内存碎片已经很大,能够经过安全重启的方式减少内存碎片:由于重启以后,Redis从新从备份文件中读取数据,在内存中进行重排,为每一个数据从新选择合适的内存dan元,减少内存碎片。网络
jemalloc做为Redis的默认内存分配器,在减少内存碎片方面作的相对比较好。jemalloc在64位系统中,将内存空间划分为小、大、巨大三个范围;每一个范围内又划分了许多小的内存块单位;当Redis存储数据时,会选择大小最合适的内存块进行存储。app
jemalloc划分的内存dan元以下图所示:负载均衡
在Redis中,实现高可用的技术主要包括持久化、复制、哨兵和集群,下面分别说明它们的做用,以及解决了什么样的问题。函数
持久化的功能:Redis是内存数据库,数据都是存储在内存中,为了不进程退出致使数据的永久丢失,须要按期将Redis中的数据以某种形式(数据或命令)从内存保存到硬盘;当下次Redis重启时,利用持久化文件实现数据恢复。除此以外,为了进行灾难备份,能够将持久化文件拷贝到一个远程位置。性能
Redis持久化分为RDB持久化和AOF持久化:前者将当前数据保存到硬盘,后者则是将每次执行的写命令保存到硬盘(相似于MySQL的binlog);因为AOF持久化的实时性更好,即当进程意外退出时丢失的数据更少,所以AOF是目前主流的持久化方式,不过RDB持久化仍然有其用武之地。
将当前进程中的数据生成快照保存到硬盘(所以也称做快照持久化),保存的文件后缀是rdb;当Redis从新启动时,能够读取快照文件恢复数据。
手动触发:save命令和bgsave命令均可以生成RDB文件。
save命令会阻塞Redis服务器进程,直到RDB文件建立完毕为止,在Redis服务器阻塞期间,服务器不能处理任何命令请求(save基本被废弃)。而bgsave命令会建立一个子进程,由子进程来负责建立RDB文件,父进程(即Redis主进程)则继续处理请求。
自动触发:自动触发最多见的状况是在配置文件中经过save m n,指定当m秒内发生n次变化时,会触发bgsave。
Redis的save m n,是经过serverCron函数、dirty计数器、和lastsave时间戳来实现的。
serverCron是Redis服务器的周期性操做函数,默认每隔100ms执行一次;该函数对服务器的状态进行维护,其中一项工做就是检查 save m n 配置的条件是否知足,若是知足就执行bgsave。
dirty计数器是Redis服务器维持的一个状态,记录了上一次执行bgsave/save命令后,服务器状态进行了多少次修改(包括增删改);而当save/bgsave执行完成后,会将dirty从新置为0。
lastsave时间戳也是Redis服务器维持的一个状态,记录的是上一次成功执行save/bgsave的时间。
RDB载入:
RDB文件的载入工做是在服务器启动时自动执行的,并无专门的命令。可是因为AOF的优先级更高,所以当AOF开启时,Redis会优先载入AOF文件来恢复数据;只有当AOF关闭时,才会在Redis服务器启动时检测RDB文件,并自动载入。服务器载入RDB文件期间处于阻塞状态,直到载入完成为止。
因为须要记录Redis的每条写命令,所以AOF不须要触发,下面介绍AOF的执行流程。
AOF的执行流程包括:
文件重写是指按期重写AOF文件,减少AOF文件的体积。须要注意的是,AOF重写是把Redis进程内的数据转化为写命令,同步到新的AOF文件;不会对旧的AOF文件进行任何读取、写入操做!
文件重写之因此可以压缩AOF文件,缘由在于:
AOF重写过程:
伪客户端:由于Redis的命令只能在客户端上下文中执行,而载入AOF文件时命令是直接从文件中读取的,并非由客户端发送;所以Redis服务器在载入AOF文件以前,会建立一个没有网络链接的客户端,以后用它来执行AOF文件中的命令,命令执行的效果与带网络链接的客户端彻底同样。
RDB持久化
AOF持久化
父进程经过fork操做能够建立子进程,子进程建立后,父子进程共享代码段,不共享进程的数据空间,可是子进程会得到父进程的数据空间的副本。在操做系统fork的实际实现中,基本都采用了写时复制技术,即在父/子进程试图修改数据空间以前,父子进程实际上共享数据空间;可是当父/子进程的任何一个试图修改数据空间时,操做系统会为修改的那一部分(内存的一页)制做一个副本。虽然fork时,子进程不会复制父进程的数据空间,可是会复制内存页表(页表至关于内存的索引、目录);父进程的数据空间越大,内存页表越大,fork时复制耗时也会越多。
若是Redis单机内存达到了10GB,fork时耗时可能会达到百毫秒级别