Redis常问的面试问题
redis优点:
1.存取数据快,且可以将数据持久化,存储模式采用多路复用(这也是为啥redis被称为单线程模型);
2.支持的数据结构多:string,最大存储512m;list(lpush, lpop);zset,有序,去重,可以按照分数范围查询;
set;hash(hmset key field1 value field2 value2 / hgetall);
3.构建集群后可以备份数据;
其他补充:
端口: 6379;
查看redis集合的大小:scard key;
string 和 hash:
在日常操作中,且从业务上说,只要能用其他的类型,就是可以用string类型。但存在一个问题,string 用起来时不灵活,而hash存放了一个对象,所以,如果时修改这个对象中的一个属性的时候,string类型需要把整个对象都取出来,修改之后再放回去,而hash则不用,它可以直接修改属性。list和string也是如此。
持久化RDB和AOF:
RDB(redis database):是指用数据集快照的方式版持久化模式。rds常用于数据版本恢复,他的运行机制也是这样,指定在特定的时间点,或者是间隔多长时间进行持久化,redis会分出一个线程来执行,如果数据级很大的话,这个操作是非常耗时的。所以,这种情况在服务器宕机的情况下作为数据恢复是会对视数据的。那么丢失的数据就是持久化之后到宕机这段时间的。在整个持久化过程结束之后,会将当前持久话的数据把原来的数据覆盖掉,这个数据文件只有一个叫做dump.rdb;
配置: save 100 1 save 900 1
AOF(append only file):类似于日志文件,会把写操作追加到后边。而他的触发条件多样,最小可以设置1s一次持久化,所以,即使宕机,也只会丢失1s的数据。aof在触发的时候会调用系统的fsyn方法,将数据缓存到操作系统的cache中,并刷新的磁盘;
配置:appendonly yes appendfsync alway|everysec|no(默认是30s)
所以,aof在服务器宕机的数据恢复中式很好用的,但是不推荐使用单纯使用aof,因为aof在数据恢复式很慢,且文件大小很大,造成bug的几率也高,所以,推荐使用rdb和aof的合用。
redis数据恢复:
redis在持久化的时候,可以将备份数据放到云服务上,当服务器宕机需要重启的时候,可以将持久化文件放到指定的目录,redis重启之后,会自动加载文件,恢复数据,如果文件既有rdb,又有aof,默认会以aof为准,因为aof的数据是比交全。
redis过期key删除策略:
定时删除:在设置键过期的同时,创建一个定时器,让定时器在key过期的时候执行key的删除;
惰性删除:放任键不管,但是每次从内存中去除改key的数据的时候,都会检查是否过期,如果过期就删除,如果没有过期就返回该键;
定期删除:没过一定时间就查询数据库,从数据库中删除过期的key,具体删除的key式多少是由算法决定的;
所以,redis的key过期式用定期删除 + 惰性删除;但是这里只是说明key不可以被查询到了,但是key还式在内存中的。
reids淘汰策略(3 + 2 + 1):
volatile-lru:在过期的数据集中,选择最不常用的key进行内存删除;
volatile-random: 在过期的数据集中,随机选择key进行内存删除;
volatile-ttl: 在过期的数据集中,选择过期的key进行内存淘汰;
allkey-lru:在所有的数据集中,选择最不常用的key进行删除;(推荐使用)
allkey-random: 在所有的数据集中,随机选择key进行内存删除;
no-envication: 禁止淘汰数据;
自己手写的lru可以选择继承linkedhashmap,并且重载是否淘汰的方法:removeEldestEntry方法;
配置: maxmemor-policy allkey-lru
redis在什么情况下导致集群不可用:
redis中一共有16384个槽点,所以集群主节点会将这些槽点分配下来,如果主节点挂掉,对应的从节点无法补上的话,那么这个集群就挂掉了。这种事在redis cluster模式下的问题。
redis的hash槽的概念:
每个key通过crc16方法对key做散列算法,结果值于16384取模,得到对应的槽点;那么这个数据就会存在于这个槽点之中;
如何从redis中拿取以固定开头的key:【这里有个坑】
首先可以用keys指令;但是keys指令会有一个问题,就是因为他是单线程执行的,所以如果这个要拿取的数据很大的话,会造成阻塞,那么,其他的操作也会被阻塞,就是一般说的死锁,所以,一般公司会将keys命令给禁用,然后推荐使用scan;
scan是非阻塞的,不过取出来的数据会有一定的重复,需要自己去去重;而scan的原理就是将keys一次性获取改成了多次获取。
缓存击穿,穿透,雪崩:
穿透的意思是说,请求查询缓存,但是缓存中没有,于是查询数据库,但是数据库中没有,造成缓存穿透,是一个缓存命中的问题;穿透式说某一个key突然失效,所以大量的请求都打到了数据库造成了缓存击穿;雪崩是说缓存层突然挂掉了,所有的请求都会直接到达数据库;
所以对数据本身为空的时候,要设置一个为空的标识;对于各种缓存,应该设置不同的失效时间,即使失效时间相同,那也要在该时间内设置随机事件,保证不会在同一时刻有大量的查询打到db上就可以。
redis的单线程模式为啥那么快:
redis实现了一个叫做事件管理器的东西,内部有多路复用技术,而单线程主要体现在这里吧,多路复用的机制中,只需要一个线程会不停的接受来自客户端的连接,然后将传入的这个时间压入一个队列,这里还有一个事件分派器,会根据事件的类型不同的处理器,处理器分成连接处理器,命令请求处理器,命令回去处理器; 这种处理机制很像nio;
redis的读写分离(master-slave):
一个主的master,多个从slave,主节点负责写,从节点负责读,主节点将数据同步到从节点,如果要支持高并发,只需要增加slave节点即可。
主从复制是异步的,slave节点也是发送请求到master节点,询问数据是否同步完成。再过程中一定对master节点使用持久化,如果不做持久化,master节点宕机之后自动重启,那么数据再内存中就会全部丢失,slave节点和maser节点进行数据同步也将数据全部清空(实在没有来的及将slave节点变成master节点)。当然,如果用的这个redis只是永来做数据缓存的话,是可以不开启持久化的。
redis主从复制过程:
slave节点启动之后,master节点会将当前的RDB持久化文件全量传输给slave节点,slave节点接收到RDB文件之后,再本地保存,并将RDB文件读取到内存中去,这是一次全量的数据同步,而再次过程中新产生的数据,会通过正常的异步数据同步到slave节点。
除此之外,还又其他的高级特性,redis支持断点续传,再master的内存中会维护一个backlog,里边会保存数据传输到那个offset偏移量,当机器在全量复制中从断开状态到连接状态,数据同步会从offset偏移量处继续传输; 过期key处理,slave不会处理过期key,他会同步master的delete操作; 无磁盘复制,master在内存中直接创建RDB发给slave,不进行磁盘文件存储。
redis做故障恢复过程:
这里如果master用rdb冷备进行数据恢复的话(就是说master节点挂掉了,选举新的节点为master, run id 会发生改变),master的run id 会发生改变,那么slave发现run id 不一样,就会发送一次全量的复制给slave。
全量复制和增量复制:
redis 高可用:redis有多种集群模式,这里说俩种:
第一种是redis-cluster模式;redis一共16384个槽,而每个节点会从这些槽点中分配一部分,每一个key进入到redis节点之后通过crc的hash函数求值然后和16384取余数,然后放入对应的节点之中,当集群有有节点宕机,最终导致有槽点段丢失,redis集群不可用。在这种集群模式中,数据传输采用二进制。各个节点彼此互联,所以客户端直接连接一台机器就可以进行访问,而不是代理层。
redis的主从复制+哨兵机制:
哨兵的功能(哨兵(sentinal)也是一个集群):集群监控,负责master和slave的进程是否正常的工作; 故障转移,master挂掉之后,选举slave作为master节点,并将新的amster节点的ip和端口发送给客户端;消息通知,将消息发送给管理远; 这之中故障转移时需要大多数的哨兵节点发起投票的,当哨兵节点挂掉之后,真个哨兵集群还时可以工作的,也就是说哨兵也是需要有高可用的功能。
主从复制+哨兵模式只能保证集群的高可用,但是不能满足数据不丢失。
哨兵节点一般会选择3太机器(奇数台),并且这只quorum = 2, 和 majortiry = 2,就是说如果哨兵节点发生故障,那么需要有俩太机器确认投票就可以重新选举master节点,而主从发生故障,俩太以上的哨兵确认投票成功就可以进行故障转移。
redis主从复制+哨兵模式数据丢失以及解决方案:
master 节点挂掉之后,有一部分数据没有来的急通过异步数据同居到slave节点中;集群发生网络错误,master节点和哨兵集群心跳丢失,哨兵重新选择slave节点为master节点,旧的master节点恢复心跳,再次期间,旧的master节点和客户端有新的数据产生,那么就master节点会变成slave节点,造成就master节点的数据丢失。
配置min-slaves-to-write 和 min-slave-max-lag, 前者是至少又几太机器要保证在多少秒(后者配置)的延迟之内数据丢失,旧的master就会拒绝接受client的消息,这样会将消息丢失控制在一定范围内。
哨兵的sdown和odown:
sdown是主观宕机,就是一台哨兵根据配置认为master节点宕机了,odown是客观宕机,是在配置quorum的情况下,quorum台机器认为master节点down了。
redis集群中,slave节点背选举为master节点:
1. 按照slave的slave-priority排序,数值越小优先级越低;
2.按照offset排序,offset越靠后,优先级越高;(同步的数据多)
3.利用runid小的slave,每个slave都有不同的run id;