Redis 的数据过期淘汰策略?
Redis 中数据过期策略采用:【定期删除】+【惰性删除策略】+【内存淘汰机制】
定期删除策略:Redis 启用一个定时器定时监视所有的 key,判断key是否过期,过期的话就删除。这种策略可以保证过期
的 key 最终都会被删除,
但是也存在严重的缺点:每次都遍历内存中所有的数据,非常消耗 CPU 资源,并且当 key 已过期,但是定时器还处于未唤
起状态,这段时间内 key 仍然可以用
惰性删除策略:在获取 key 时,先判断 key 是否过期,如果过期则删除。
这种方式存在一个缺点:如果这个 key 一直未被使用,那么它一直在内存中,其实它已经过期了,会浪费大量的空间。
这两种策略天然的互补,结合起来之后,定时删除策略就发生了一些改变,不在是每次扫描全部的 key 了,而是【随机抽取一部分】key 进行检查,这样就降低了对 CPU资源的损耗,惰性删除策略互补了为检查到的key,基本上满足了所有要求。
但是有时候就是那么的巧,既没有被定时器抽取到,又没有被使用,这些数据又如何从内存中消失?没关系,还有内存淘汰机制,当内存不够用时,内存淘汰机制就会上场。Redis 内存淘汰机制有以下几种策略:
内存淘汰机制:
1、不考虑过期时间
noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。(Redis 默认策略)
allkeys-LRU:当内存不足以容纳新写入数据时,在键空间中,【移除最近最少】使用的 Key。(推荐使用)
allkeys-random:当内存不足以容纳新写入数据时,在键空间中,【随机】移除某个 Key
2、基于过期时间判断
volatile-lru:当内存不足以容纳新写入数据时,在【设置了过期时间的键空间中】,移除最近【最少使用的Key】。
这种情况一般是把Redis既当缓存,又做持久化存储的时候才用。
volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个Key。
volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的Key优先移除。
其实就是选择那些即将过期的键进行淘汰
4.0之后又增加了两种淘汰算法
为什么快:
1、基于内存
2、独特的数据结构
3、单线程,减少了锁定判断
4、使用了IO多路复用。
Redis 持久化有几种方式?
Redis 的持久化有两种方式,或者说有两种策略:
RDB(Redis Database):指定的时间间隔能对你的数据进行快照存储。
AOF(Append Only File):每一个收到的写命令都通过write函数追加到文件中。
redis的持久化机制是什么?各自的优缺点?
目前有两种持久化机制:RDB和AOF机制。
RDB持久化机制:用数据集快照的方式半持久化模式,记录redis数据库的所有键值对,在某个时间点将数据写入一个临时文件,
持久化结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。
优点:只有一个文件dump.rdb,方便持久化;容灾性好,一个文件可以保存到安全的磁盘;性能最大化,
fork子进程来完成写操作,让主进程继续处理命令,所以是IO最大化。相对于数据集发时,比AOF的启动效率更高。
缺点:数据安全性低,RDB是间隔一段时间进行持久化,如果持久化期间发生redis故障,会导致数据丢失,
所以这种方式更适合数据要求不严谨的。
AOF持久化
是指所有的命令行记录以redis命令请求协议的格式完全持久化存储保存为aof文件。
优点:数据安全,aof持久化可以配置appendfsync属性,有always,每次操作都记录到aof文件中;
通过append模式写文件,即使中途服务器宕机,也可以通过redis-check-aof工具解决数据一致性问题;
aof机制的rewrite模式,AOF 文件没被 rewrite 之前(文件过大时会对命令进行合并重写),
可以删除其中的某些命令(比如误操作的 flushall))
缺点:AOF文件比RDB文件大,所以恢复速度慢;数据集大的时候,比 rdb 启动效率低。
redis同步机制
redis可以使用主从同步,从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将【rdb文件全量同步到复制节点】,复制节点接受完成后将rdb镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。
说说 Redis 哈希槽的概念
redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群中有16384个哈希槽,每个key通过crc16校验后对16384取模来决定放在哪个槽,集群的每个节点负责一部分哈希槽。
分布式锁实现:
Boolean ifAbsent = valueOperations.setIfAbsent(key, value, 30, TimeUnit.SECONDS);
面试题原文 《跳转》