一、Redis为何这么快

1.官方提供的数据表示Redis可以达到10w+的QPS(每秒查询次数)

2.Redis是单线程单进程的模型,Redis完全基于内存操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章的采用单线程方案了。

3.使用多路复用IO模型,非阻塞IO。

 

二、Redis和Memached的区别

1.存储方式上:Memached会把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。Redis有部分数据存在硬盘上,这样保证了数据的持久性。

2.数据支持类型上:Memached对数据类型的支持简单,只支持简单的key-value,而Redis支持五种数据类型。

3.使用底层模型不同:它们之间底层实现方式以及与客户端之间通信的应用协议不一样。Redis直接自己构建了VM机制,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。

4.value的大小:Redis可以达到1GB,而Memached只有1MB。

 

三、Redis的淘汰策略

1.volatile-Iru: 从已设置过期时间的KV集中优先对最近最少使用(less recently used)的数据淘汰。

2.volatile-ttl:从已设置过期时间的KV集中优先对剩余时间短(time to live)的数据淘汰。

3.volatile-random:从已设置过期时间的KV集中随机选择数据淘汰。

4.allkeys-Iru:从所有KV集中优先对最近最少使用(less recently used)的数据淘汰。

5.allkeys-random:从所有KV集中随机选择数据淘汰。

6.noeviction:不淘汰策略,若超过最大内存,返回错误信息。

7.volatile-lfu:从已设置过期时间的KV集中,统计访问频率,将访问频率最少,即最不经常使用的KV淘汰。

8.allkeys-lfu:从所有KV集中,统计访问频率,将访问频率最少,即最不经常使用的KV淘汰。

 

四、Redis的持久化

    Redis为了保证效率,数据缓存在了内存中,但是会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件中,以保证数据的持久化。

Redis的持久化策略有两种:

1、RDB:快照形式是直接把内存中的数据保存到一个dump文件中,定时保存,保存策略。

2、AOF:把所有的对Redis的服务器进行修改的命令都存到一个文件里,命令的集合。

 

    Redis默认是快照RDB的持久化方式。当Redis重启的时候,它会优先使用AOF文件来还原数据集,因为AOF文件保存的数据集通常比RDB文件所保存的数据集更完整。你甚至可以关闭持久化功能,让数据只在服务器运行时存。

 

RDB的工作原理:

    当Redis需要做持久化时,Redis会fork一个子进程,子进程将数据写到磁盘上一个临时RDB文件中,当子进程完成写临时文件后,将原来的RDB替换掉,这样的好处是可以copy-on-write.

 

RDB的优点:

    这种文件非常适用于备份,比如,你可以在最近的24小时内,每小时备份一次,并且在每个月的每一天也备份一个RDB文件。这样的话,即使遇上问题,也可以随时将数据集还原到不同的版本。RDB非常适合灾难恢复。

 

RDB的缺点:

    如果需要尽量避免在服务器故障时丢失数据,那么RDB不适合。

 

AOF的工作原理:

    AOF可以做到全程持久化,只需要再配置中开启appendonly yes。 这样Redis每执行一个修改数据的命令,都会把它添加到AOF文件中,当Redis重启时,将会读取AOF文件进行重放,恢复Redis关闭前的最后时刻。

    

AOF的优点:

    使用AOF的优点是会让Redis变得非常耐久,可以设置不同的fsync策略,aof的默认策略是每秒钟fsync一次,在这种配置下,就算发生故障停机,也最多丢失一秒钟的数据。

 

AOF的缺点:

    对于相同的数据集来说,AOF的文件体积通常要大于RDB文件的体积。根据所使用的fsync策略,AOF的速度可能会慢于RDB。

 

RDB和AOF如何选择:

    如果非常关系新数据,但是仍然可以承受数分钟内的数据丢,那么可以只是用RDB持久。因为AOF会将Redis执行的每一条命令追加到磁盘中,处理巨大的写入会降低Redis的性能。定时生成RDB快照非常便于进行数据库备份,并且RDB恢复数据集的速度也要比AOF恢复的速度快。当然了,Redis支持同时开启RDB和AOF,系统重启后,Redis会优先使用AOF来恢复数据,这样丢失的数据会最少。

 

五、Redis的主从复制

    主从配置结合哨兵模式能解决单点故障问题,提高Redis可用性。从节点仅提供读操作,主节点提供写操作。对于读多写少的状况,可给主节点配置多个从节点,从而提高响应效率。

    1)复制的过程:

1.从节点执行slaveof[masterIP][masterPort],保存主节点信息。

2.从节点中的定时任务发现主节点信息,建立和主节点对的socket连接

3.从节点发送Ping信号,主节点返回Pong,两边能互相通信

4.连接建立后,主节点将所有数据发送给从节点(数据同步)

5.主节点把当前的数据同步给从节点后,便完成了复制的建立过程。接下来,主节点就会持续的把写命令发送给从节点,保证主从数据一致性。

 

    2)Redis主从节点数据同步的过程:

    Redis2.8之前使用sync[runId][offset]同步命令,Redis2.8之后使用psync[ronId][offset]命令。两者不同在于,sync命令仅支持全量复制过程,psync支持全量和部分复制。介绍同步之前,先介绍几个概念:

 

1.runId:每个Redis节点启动都会生成唯一的uuid,每次Redis重启后,runId都会发生变化。

2.offset:主节点和从节点都各自维护自己的主从复制偏移量offset,当主节点有写入命令时,offset=offset+命令的字节长度。从节点在收到主节点发送的命令后,也会增加自己的offset,并把自己的offset发送给主节点。这样,主节点同时保存自己的offset和从节点的offset,通过对比offset来判断主从节点的数据是否一致。

3.repl_backlog_size:保存在主节点上的一个固定长度的先进先出队列,默认大小是1MB。

 

    1)主节点发送数据给从节点过程中,主节点还会进行一些写操作,这时候的数据存储在复制缓冲区中。从节点同步主节点数据完成后,主节点将缓冲区的数据继续发送给从节点,用于部分复制。

    2)主节点响应写命令时,不但会把命名发送给从节点,还会写入复制挤压缓冲区,用于复制命令丢失的数据补救。

 

    从节点发出psync[runId][offset]命令,主节点有三种响应:

1.FULLRESYNC:第一次连接,进行全量复制。

2.CONTINUE:进行部分复制。

3.ERR:不支持psync命令,进行全量复制。

 

六、哨兵

主从复制会存在以下问题:

1.主节点宕机,从节点晋升为主节点,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预。

2.主节点的写能力收到单机的限制。

3.主节点的存储能力收到单机的限制。

4.原生复制的弊端在早期的版本也会比较突出,比如:Redis复制中断后,从节点会发起psync。此时如果同步不成功,则会进行全量同步,主库执行全量备份的同时,可能会造成毫秒级的卡顿。

 

针对以上问题,比较主流的解决方案是哨兵。

 

哨兵的主要功能:主节点存活检测、主从运行情况检测、自动故障转移、主从切换。

1.监控:不断检查主服务器和从服务器是否正常运行。

2.通知:当被监控的某个Redis服务器出现问题,哨兵通过API脚本向管理员或者其他应用程序发出通知。

3.自动故障转移:当主节点不能正常工作时,哨兵会开始一次自动的故障转移操作,它会将与失效主节点是主从关系的其中一个从节点升级为新的主节点,并且将其他的从节点指向新的主节点,这样人工干预就可以免除。

4.配置提供者:在哨兵模式下,客户端应用在初始化时连接的是哨兵节点集合,从中获取主节点的信息。

 

哨兵的工作原理:

1.每个哨兵都需要定期执行任务:每个哨兵以每秒一次的频率,向它所知的主服务器、从服务器以及其他的哨兵实例发送一个PING命令。

2.如果一个实例距离最后一次有效回复PING命令的时间超过down-after-milliseconds所指定的值,那么这个实例会被哨兵标记为主观下线。

3.如果一个主服务器被标记为主观下线,那么正在监视这个服务器的所有哨兵节点,要以每秒一次的频率确认主服务器的确进入了主观下线状态。

4.如果一个主服务器被标记为主观下线,并且有足够数量的哨兵(至少要达到配置文件指定的数量)在指定的时间范围内同意这一判断段,那么这个主服务器被标记为客观下线。

5.一般情况下,每个哨兵会以每10秒一次的频率向它已知的所有主服务器和从服务器发送INFO命令,当一个主服务器被标记为客观下线时,哨兵向下线主服务器的所有从服务器发送INFO命令的频率,会从10s一次改为每秒一次。

6.哨兵们协商客观下线的主节点的状态,如果处于SDOWN状态,则投票自动选出新的主节点,将剩余从节点指向新的主节点进行数据复制。

7.当没有足够数量的哨兵同意主服务器下线时,主服务器的客观下线状态就会被移除。当主服务器重新向哨兵的PING命令返回有效回复时,主服务器的主观下线状态就会被移除。