序言

redis作为一个web开发者不可不用的一个好工具,关于redis,如果只是知道如何使用,那么你怎么敢说自己精通redis呢? 下面节选了redis的一些理论知识,看完之后就可以可以在简历上大胆的写下: 精通redis 啦。

redis中的过期删除策略

定时删除: 在设置键的过期时间的时候,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作;(问题:大量定时器占用cpu时间)

惰性删除: 当键过期时不管,只有需要从键空间获取键时,检查键是否已经过期,如果过期的话,删除该键,没有过期的话,返回该键;(问题:内存泄漏)

定期删除: 定期删除是指每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键,这个有多种算法来决定怎么进行删除;

若执行的比较频繁的时候,某种意义上类似于定时删除,占用了大量的cpu时间;

若执行的太少的时候,会导致跟惰性删除一样,浪费太多的内存;

redis的持久化操作

RDB持久化

关于创建与载入:

save 命令会阻塞服务器进程去生成一个RDB文件;

bgsave 命令则是派生出一个子进程,由子进程负责创建RDB文件;bgsave过程中,save命令会被服务器拒绝(避免父进程和子进程一起写),同理,bgsave也会被拒绝,另外 BGREWRITEAOF 和 BGSAVE 也是互斥的,这个是由于性能的考虑;

载入:在Redis启动的时候,如果检测到RDB文件的存在的时候,就会载入该RDB文件;(如果开启了AOF持久化功能,那么会优先使用AOF文件来还原数据库状态,否则使用过的是RDB文件来还原数据库状态);

譬如以下命令来触发bgsave:

save 900 1 表示: 900秒内对数据库进行一次修改;

AOF持久化

保存redis中的写命令来记录数据库的状态

服务器配置 appendfsync值来产生不同的持久化行为:

always: 将aof_buf缓冲区中的所有内容写入并同步到AOF文件中去;

everysec: 将aof_buf缓冲区中的所有内容写入到AOF文件,并且距离上次写入超过一秒钟,那么就通过新起一个线程的方式对AOF文件进行同步(这个是默认值);

no:将 aof_buf 缓冲区中的文件写入到AOF文件中,但不对AOF文件进行同步,何时是由操作系统来决定的。(这个需要关注操作系统中的文件的写入和同步机制)

还原机制:创建一个不带网络连接的伪客户端(毕竟是从文件中恢复的),然后分析AOF文件去读取并执行,直到文件并更新完成;

由上面就可以直到,由于AOF的实时,导致会存在一些冗余的命令 ,所以redis支持AOF重写,即redis命令的简化。(BGREWRITEOF,这个过程是新生成一个AOF文件,向父进程发起一个信号,让父进程将服务器的写命令都放进AOF重写缓冲区【也会照常放进去AOF缓冲区】,直到完成重写之后,对新的AOF文件进行改名,这个过程中是原子性的,并且只有在处理信号处理函数的时候,父进程是阻塞的,其他过程都是子进程在操作)

redis的主从机制

在redis中,我们可以通过SLAVEOF命令,让一个服务器去复制另一个服务器。

同步功能

redis2.8以前的同步操作:

特点:SYNC(生成一个RDB文件并且将后续所有的操作放到一个缓冲区里面,并将同步到从服务器中去) + 命令传播(主服务器上的所有后续的操作都将通过命令传播的形式将命令传播到从服务器)

缺陷是什么:初次复制的时候是没有什么问题但是当断线重连之后,又进行了跟之前同步一样的操作,其实是没有必要的,效率比较低;

从redis2.8开始:

使用PSYNC代替 SYNC,具备 完整重同步【用于初次复制】和部分重同步【用于断线重连修复】

部分重同步的实现:

主服务器的复制偏移量和从服务器的复制偏移量(字节);

主服务器的复制挤压缓冲区(一个固定长度的先进先出队列);

服务器的运行ID(runID,主要用于判断重连之后,主服务器是否还是原来的主服务器,如果不是的话,那么就需要进行完整的复制同步)

哨兵机制

由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主服务器,以及这些主服务器属下的所有从服务器;其作用是当被监视的主服务器进入下线状态时,自动将下线主服务器属下的某个服务器升级成新的主服务器,然后由新的主服务器代替已经下线的主服务器继续处理命令请求。

Sentinel启动的步骤如下:

初始化服务器;

将普通的redis服务器使用的代码替换成Sentinel专用代码;

初始化Sentinel状态;

根据给定的配置文件,初始化Sentinel的监视主服务器列表;

创建连向主服务器的网络连接;

当redis服务出问题的时候,sentinel操作的流程如下:

Sentinel会挑选server1属下的其中一个从服务器,并将这个被选中的从服务器升级为新的主服务器;

sentinel会将已下线的主服务器的所有从服务器保存到一个列表中,并且删除其中处于下线状态的;

删除最近5秒内没有回复过sentinel的info命令的从服务器,保证剩下的都是最近成功进行过通信的;

删除所有与已下线服务器断开超过 down-after-millseconds * 10 毫秒的从服务器;

按照优先级和从服务器的复制偏移量(与原来主服务器的数据一致性最高)

Sentinel会向server1属下的所有从服务器发送新的复制指令,将它设置为新的主服务器的从服务器,当所有从服务器都开始复制新的主服务器时,故障转移操作执行完毕;

sentinel的选举机制:

进行选举的时候,首先都会将配置纪元的值自增一次,所有的sentinel都有一次将某个sentinel设置为局部master的机会,并且设置后不能修改。另外,每个发现了原来的sentinel机器下线的机器都会要求其他人把自己设置为master,并且按照先到先得的情况。最后,得到超过半数投票的sentinel会成为新的领头sentinel,否则的话,重新进行一次选举。

备注信息

当服务器运行在复制模式下时,此刻如果有一个请求到从服务器,请求一个本该过期的键,由于从服务器还没有接收到主服务器的删除操作,就还是会像处理未过期的键一样把数据返回;