redis数据删除/内存淘汰
如果我们设置一批key只能存活1小时,那么1小时之后,redis是怎么对这批数据进行删除的?
答案:定期删数+惰性删除
(1)定期删除
指的是redis默认是每隔100ms就随机抽取一些设置了过期时间的key,检查其是否过期,如果过期就删除。注意,这里可不是每隔100ms就遍历所有的设置过期时间的key,那样就是一场性能上的灾难。实际上redis是每隔100ms随机抽取一些key来检查和删除的。
(2)惰性删除
定期删除的问题是可能会导致很多过期key到了时间并没有被删除掉,那怎么办?所以还有惰性删除,也就是在查询某个key的时候,redis会检查一下这个key如果设置了过期时间并且是否过期了,如果过期了就会在此时删除。
通过定期删除和惰性删除两种方式结合,保证过期的key一定会被删除
- 定期删除是为了节省内存
- 惰性删除是为了保证过期性
如果定期没删除,也没有查询,这样会导致大量过期的key堆积在内存里怎么办?
答案:内存淘汰机制
allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。
volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
手写LRU
public class LRUCache extends LinkedHashMap {
private final int CACHE_SIZE;
public LRUCache(int cacheSize){
/**
* 这块就是设置一个hashmap的初始大小,
* 同时最后一个true指的是让linkedHashMap按照访问顺序来进行排序(自动实现LRU)
* 最近访问的放在头,最老访问的放在尾
*/
super((int)Math.ceil(cacheSize/0.75)+1, 0.75f, true);
CACHE_SIZE = cacheSize;
}
//通过覆盖这个方法,加入一定的条件,满足条件返回true。
//当put进新的值方法返回true时,便移除该map中最老的键和值。
@override
protected boolean removeEldestEntry(Map.Entry eldest){
/**
* 这个意思就是说当map中当数据大于指定当缓存个数当时候,就会自动删除最老的数据
*/
return size() > CACHE_SIZE;
}
}
主从复制过程
这个牛客网上问的也不多,先待定二轮复习再补充
Redis哨兵模式
这都是为了提高redis的高可用性
==集群监控==,负责监控redis master和slave进程是否正常工作
==消息通知==,如果某个redis实例有故障,那么哨兵负责发送消息作为报警通知管理员
==故障转移==,如果master node挂掉了,会自动转移到slave node上
==配置中心==,如果故障转移发生了,通知client客户端新的master地址
- 命令连接:用来获取主/从服务器的信息
- 订阅连接:sentinel1会通过命令连接向主从服务器发送自身状态信息,通过订阅连接将此信息通知到其他的哨兵,因此哨兵不需要知道哨兵之间的位置
- 哨兵之间命令连接:与下线检测的原理相关(因为此时主服务器已经宕机,无法通过订阅连接让哨兵之间通知)
哨兵模式工作流程
- 每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令。
- 如果一个实例(instance)距离最后一次有效回复 PING 命令的时间超过 down-after-milliseconds 选项所指定的值, 则这个实例会被当前 Sentinel 标记为主观下线。
- 如果一个Master被标记为主观下线,则正在监视这个Master的所有 Sentinel 要以每秒一次的频率确认Master的确进入了主观下线状态。
- 当有足够数量的 Sentinel(大于等于配置文件指定的值)在指定的时间范围内确认Master的确进入了主观下线状态, 则Master会被标记为客观下线 ,进而对Master进行故障转移
故障转移流程
- 选取领头哨兵,采取先到先得的方式,超过半数哨兵的支持的哨兵成为领头哨兵
- 从已下线主服务器属下的所有从服务器里面,挑选一个从服务器,并将其转换为主服务器
- 让一下先主服务器属下所有从服务器改位复制新的主服务器
- 将已下线主服务器设置位新的主服务器的从服务器
挑选从服务器的流程
- 从服务器处于在线状态
- 从服务器最近五秒回复过哨兵的INFO命令
- 跟master断开连接的时长较短,这是为了保证从服务器的数据较新
- 从服务器优先级,复制偏移量(哪个slave复制了越多的数据,offset越靠后,优先级就越高),运行ID(run id比较小),进行排序
为什么哨兵至少需要3个
- 因为挑选领头哨兵的时候需要获得超过半数的投票,所以一般都是把哨兵的节点设置为奇数位。因为(2的majority=2,3的majority=2,5的majority=3,4的majority=3)偶数容易算错
- 2个哨兵同样可以完成功能,所以其实没有说一定要至少三个,只是两个哨兵的时候如果挂了一个就不可用了,而三个哨兵挂了一个还有两个可用。因此至少3个是为了达到一定的高可用性的常用配置而已。
Redis集群模式
redis分片
将整个数据集按照一定的规则分配到多个节点上,常用的数据分片的方法有:范围分片,哈希分片,一致性哈希算法,哈希槽等。
槽位的概念在集群这里很重要,任何key都要通过槽位分片到不同的节点运行
创建集群的流程
- 配置和开启cluster模式
- 配置redis实例节点握手
- 为每个主节点指派槽位,一般按区间平均分配
- 分配主从
扩容集群过程
- 准备新节点
- 加入集群进行握手
- 迁移槽和数据(槽位转移了,对应槽位的数据也会迁移到新的实例上)
缩容过程
- 确定下线的节点是否有负责槽,如果是,需要把槽迁移到其他节点,保证节点下线后整个槽节点映射的完整性。
- 当下线节点不在负责槽或着本身是从节点时,就可以通知集群内其他节点忘记下线节点,当所有节点忘记该节点后就可以正常关闭。
故障转移
为什么redis cluster至少需要3个主节点?
因为故障检测时没有哨兵,需要超过半数的主节点都主观下线,该故障节点才会被视为客观下线。两个主节点,如果挂了一个,那么只剩一个无法达到超过半数的条件。这与哨兵模式不同,因为两个哨兵不一定会挂。
故障转移过程-----《redis设计与实现》------感觉不会考
主从复制,哨兵,集群的区别
1.主从模式:读写分离,备份,一个Master可以有多个Slaves。
2.哨兵sentinel:监控,自动转移,哨兵发现主服务器挂了后,就会从slave中重新选举一个主服务器。
3.集群:故障转移不再需要哨兵,提供数据分片,提高并发量,一般都是使用它了。