Redis 淘汰策略
- 只有
redis
内存空间已满并且往里面写新数据,才会触发淘汰策略。 - 通过
expire
/ / /pexpire
让key-value
过期,从而让redis
清除这个key-value
。 value
的数据结构:typedef struct { // 对象类型:string、list、hash、set、zset unsigned tpye:4; // 编码方式:比如 set 使用 intset 或 dict unsigned encoding:4; // 判断哪些 key 要被删除 unsigned lru:LRU_BITS; // 占用 24位,8位用来记录访问的次数(0-255次),16位用来记录上一次访问的时间 int refcount; // 引用计数 void *ptr; // 指向 value 的存储空间 } robj;
object idletime key # 展示 key 的最近访问时间
- 配置淘汰策略:
- 如果
redis
内存空间已满,并且没有设置淘汰策略,再set key value
会直接返回错误,提示内存空间已满;如果设置了淘汰策略,redis
会按照淘汰策略选择数据进行删除,再set key value
就会成功。# redis.conf maxmemory <bytes> # redis 最多可以使用多少空间(字节) maxmemory-policy # 淘汰策略,默认为 noeviction, 不进行淘汰 maxmemory-samples # 默认为 5,选择多少个 key 进行淘汰
- 设置了过期时间的
key
:volatile-lru
:最长时间没有使用。volatile-lfu
:最少次数使用,随机采样。volatile-ttl
:最近要过期。volatile-random
:随机。
- 所有
key
:allkeys-lru
。allkeys-lfu
。allkeys-random
。
- 禁止淘汰:
no-eviction
。
- 如果
redis
不会在key
到达设定的过期时间那一刻立即自动删除,而是采用了惰性删除和定期删除的混合策略:- 惰性删除:当某个
key
被访问时,redis
会检查这个key
是否已经过期。如果已经过期,redis
会在该key
被访问时立即删除它,然后返回一个空值。这意味着,如果一个过期的key
从未被访问,它可能会在内存中保留较长时间。 - 定期删除:
redis
也会定期从数据库中随机抽取一些key
,然后检查它们是否过期,已过期的key
将被删除。这个过程是自动的,帮助减少内存中未被访问的过期key
的数量。
- 惰性删除:当某个
Redis 持久化机制
redis
为什么需要持久化 ?- 因为
redis
是内存数据库,一旦关闭,内存中的数据就丢失了,所以需要把内存中的数据写到磁盘中,这样redis
重启后就可以从磁盘中加载原来的数据到内存中。 - 只有写操作(增删改操作,会引起数据库变更的操作)才会进行持久化。
- 因为
redis
的持久化方式:aof
、aof-rewrite
、rdb
、rdb-aof
混用。
fork 写时复制
- 避免物理内存的复制时间过长导致父进程长时间阻塞。
fork
相当于给父进程的内存做了一个快照。
- 页表存储了虚拟内存和物理内存之间的映射关系。
linux
为了加快fork
的流程,fork
仅仅会复制页表,然后将两个页表中的所有保护位修改为只读,此时父进程和子进程共用一块物理内存;父进程依然对外提供服务。- 当父进程处理写操作时,首先会找到虚拟内存的内存页,然后通过页表写物理内存页的时候,发现保护位是只读的,此时会触发写保护中断:在物理内存中完成一次物理页复制(把原来的物理页复制一份),然后把数据写入到复制后物理页中,最后在写保护中断的处理函数中将页表中的保护位修改为可读可写,并且重新构建页表中的映射关系(页表中该虚拟内存的指向变为新的物理页)。